コード例 #1
0
 def setUp(self):
     import os
     import tempfile
     from repoze.sendmail.queue import QueueProcessor
     self.dir = tempfile.mkdtemp()
     self.maildir_path = os.path.join(self.dir, 'Maildir')
     self.qp = QueueProcessor(_makeMailerStub(), self.maildir_path)
コード例 #2
0
 def setUp(self):
     from repoze.sendmail.queue import QueueProcessor
     self.qp = QueueProcessor()
     self.qp.maildir = MaildirStub('/foo/bar/baz')
     self.qp.mailer = MailerStub()
     self.qp.log = LoggerStub()
     self.dir = mkdtemp()
コード例 #3
0
ファイル: mailout.py プロジェクト: reebalazs/karl
def main():
    parser = optparse.OptionParser(description=__doc__, usage="%prog [options] queue_path")
    parser.add_option(
        "-C",
        "--config",
        dest="config",
        default=None,
        help="Path to configuration file (defaults to $CWD/etc/karl.ini)",
        metavar="FILE",
    )
    parser.add_option("--daemon", "-D", dest="daemon", action="store_true", default=False, help="Run in daemon mode.")
    parser.add_option(
        "--interval",
        "-i",
        dest="interval",
        type="int",
        default=6 * 3600,
        help="Interval, in seconds, between executions when in " "daemon mode.",
    )
    parser.add_option(
        "--server", "-s", dest="hostname", default="localhost", help="SMTP server host name", metavar="HOST"
    )
    parser.add_option("--port", "-P", dest="port", type="int", default=25, help="Port of SMTP server", metavar="PORT")
    parser.add_option("--username", "-u", dest="username", default=None, help="Username, if authentication is required")
    parser.add_option("--password", "-p", dest="password", default=None, help="Password, if authentication is required")
    parser.add_option(
        "--force-tls", "-f", dest="force_tls", action="store_true", default=False, help="Require that TLS be used."
    )
    parser.add_option(
        "--no-tls", "-n", dest="no_tls", action="store_true", default=False, help="Require that TLS not be used."
    )

    options, args = parser.parse_args()

    if not args:
        parser.error("Please specify queue path.")
    elif len(args) > 1:
        parser.error("Too many arguments.")
    queue_path = args[0]

    config = options.config
    if config is None:
        config = get_default_config()
    app = loadapp("config:%s" % config, "karl")
    set_subsystem("mailout")

    mailer = SMTPMailer(
        hostname=options.hostname,
        port=options.port,
        username=options.username,
        password=options.password,
        no_tls=options.no_tls,
        force_tls=options.force_tls,
    )
    qp = QueueProcessor(mailer, queue_path)

    if options.daemon:
        run_daemon("digest", qp.send_messages, options.interval)
    else:
        qp.send_messages()
コード例 #4
0
ファイル: mailout.py プロジェクト: boothead/karl
def main():
    parser = optparse.OptionParser(
        description=__doc__,
        usage="%prog [options] queue_path",
    )
    parser.add_option('-C', '--config', dest='config',
        default=None,
        help='Path to configuration file (defaults to $CWD/etc/karl.ini)',
        metavar='FILE')
    parser.add_option('--daemon', '-D', dest='daemon',
                      action='store_true', default=False,
                      help='Run in daemon mode.')
    parser.add_option('--interval', '-i', dest='interval', type='int',
                      default=6*3600,
                      help='Interval, in seconds, between executions when in '
                           'daemon mode.')
    parser.add_option('--server', '-s', dest='hostname', default="localhost",
                      help='SMTP server host name', metavar='HOST')
    parser.add_option('--port', '-P', dest='port', type='int', default=25,
                      help='Port of SMTP server', metavar='PORT')
    parser.add_option('--username', '-u', dest='username', default=None,
                      help='Username, if authentication is required')
    parser.add_option('--password', '-p', dest='password', default=None,
                      help='Password, if authentication is required')
    parser.add_option('--force-tls', '-f', dest='force_tls',
                      action='store_true', default=False,
                      help='Require that TLS be used.')
    parser.add_option('--no-tls', '-n', dest='no_tls',
                      action='store_true', default=False,
                      help='Require that TLS not be used.')

    options, args = parser.parse_args()

    if not args:
        parser.error('Please specify queue path.')
    elif len(args) > 1:
        parser.error('Too many arguments.')
    queue_path = args[0]

    config = options.config
    if config is None:
        config = get_default_config()
    app = loadapp('config:%s' % config, 'karl')
    set_subsystem('mailout')

    mailer = SMTPMailer(
        hostname=options.hostname,
        port=options.port,
        username=options.username,
        password=options.password,
        no_tls=options.no_tls,
        force_tls=options.force_tls
    )
    qp = QueueProcessor(mailer, queue_path)

    if options.daemon:
        run_daemon('digest', qp.send_messages, options.interval)
    else:
        qp.send_messages()
コード例 #5
0
class TestQueuedMailDeliveryWithMaildir(unittest.TestCase):
    def setUp(self):
        import os
        import tempfile
        from repoze.sendmail.queue import QueueProcessor

        self.dir = tempfile.mkdtemp()
        self.maildir_path = os.path.join(self.dir, "Maildir")
        self.qp = QueueProcessor(_makeMailerStub(), self.maildir_path)

    def tearDown(self):
        import shutil

        shutil.rmtree(self.dir)

    def _getTargetClass(self):
        from repoze.sendmail.delivery import QueuedMailDelivery

        return QueuedMailDelivery

    def _makeOne(self, queuePath="/tmp"):
        return self._getTargetClass()(queuePath)

    def test_send_w_non_ASCII_addrs(self):
        import os
        from email.mime import base
        import transaction
        from repoze.sendmail._compat import b

        delivery = self._makeOne(self.maildir_path)

        non_ascii = b("LaPe\xc3\xb1a").decode("utf-8")
        fromaddr = non_ascii + " <*****@*****.**>"
        toaddrs = (non_ascii + " <*****@*****.**>",)
        message = base.MIMEBase("text", "plain")
        message["From"] = fromaddr
        message["To"] = ",".join(toaddrs)

        delivery.send(fromaddr, toaddrs, message)
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, "tmp")))
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, "new")))
        transaction.commit()
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, "tmp")))
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, "new")))

        self.qp.send_messages()
        self.assertTrue(len(self.qp.mailer.sent_messages), 1)
        queued_fromaddr, queued_toaddrs, queued_message = self.qp.mailer.sent_messages[0]
        self.assertEqual(queued_fromaddr, fromaddr)
        self.assertEqual(queued_toaddrs, toaddrs)
コード例 #6
0
ファイル: mailout.py プロジェクト: davidblewett/karlserve
def main(args):
    queue_path = args.get_setting('mail_queue_path')
    set_subsystem('mailout')

    mailer = SMTPMailer(
        hostname=args.server,
        port=args.port,
        username=args.username,
        password=args.password,
        no_tls=args.no_tls,
        force_tls=args.force_tls
    )
    qp = QueueProcessor(mailer, queue_path)
    qp.send_messages()
コード例 #7
0
ファイル: zcml.py プロジェクト: MatthewWilkes/repoze.sendmail
    def createQueuedDelivery():
        delivery = QueuedMailDelivery(queuePath)

        handler('registerUtility', delivery, IMailDelivery, name)

        mailerObject = queryUtility(IMailer, mailer)
        if mailerObject is None:
            raise ConfigurationError("Mailer %r is not defined" % mailer)

        if processorThread:
            qp = QueueProcessor()
            qp.mailer = mailerObject
            qp.queue_path = queuePath
            delivery.processor_thread = qp.send_messages_thread()
コード例 #8
0
ファイル: zcml.py プロジェクト: MatthewWilkes/repoze.sendmail
    def createQueuedDelivery():
        delivery = QueuedMailDelivery(queuePath)

        handler('registerUtility', delivery, IMailDelivery, name)

        mailerObject = queryUtility(IMailer, mailer)
        if mailerObject is None:
            raise ConfigurationError("Mailer %r is not defined" %mailer)

        if processorThread:
            qp = QueueProcessor()
            qp.mailer = mailerObject
            qp.queue_path = queuePath
            delivery.processor_thread = qp.send_messages_thread()
コード例 #9
0
class TestQueuedMailDeliveryWithMaildir(unittest.TestCase):

    def setUp(self):
        import os
        import tempfile
        from repoze.sendmail.queue import QueueProcessor
        self.dir = tempfile.mkdtemp()
        self.maildir_path = os.path.join(self.dir, 'Maildir')
        self.qp = QueueProcessor(_makeMailerStub(), self.maildir_path)

    def tearDown(self):
        import shutil
        shutil.rmtree(self.dir)

    def _getTargetClass(self):
        from repoze.sendmail.delivery import QueuedMailDelivery
        return QueuedMailDelivery

    def _makeOne(self, queuePath='/tmp'):
        return self._getTargetClass()(queuePath)

    def test_send_w_non_ASCII_addrs(self):
        import os
        from email.mime import base
        import transaction
        from repoze.sendmail._compat import b
        delivery = self._makeOne(self.maildir_path)

        non_ascii = b('LaPe\xc3\xb1a').decode('utf-8')
        fromaddr = non_ascii + ' <*****@*****.**>'
        toaddrs = (non_ascii + ' <*****@*****.**>',)
        message = base.MIMEBase('text', 'plain')
        message['From'] = fromaddr
        message['To'] = ','.join(toaddrs)

        delivery.send(fromaddr, toaddrs, message)
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'new')))
        transaction.commit()
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'new')))

        self.qp.send_messages()
        self.assertTrue(len(self.qp.mailer.sent_messages), 1)
        queued_fromaddr, queued_toaddrs, queued_message = (
            self.qp.mailer.sent_messages[0])
        self.assertEqual(queued_fromaddr, fromaddr)
        self.assertEqual(queued_toaddrs, toaddrs)
コード例 #10
0
class TestQueuedMailDeliveryWithMaildir(unittest.TestCase):

    def setUp(self):
        import os
        import tempfile
        from repoze.sendmail.queue import QueueProcessor
        self.dir = tempfile.mkdtemp()
        self.maildir_path = os.path.join(self.dir, 'Maildir')
        self.qp = QueueProcessor(_makeMailerStub(), self.maildir_path)

    def tearDown(self):
        import shutil
        shutil.rmtree(self.dir)

    def _getTargetClass(self):
        from repoze.sendmail.delivery import QueuedMailDelivery
        return QueuedMailDelivery

    def _makeOne(self, queuePath='/tmp'):
        return self._getTargetClass()(queuePath)

    def test_send_w_non_ASCII_addrs(self):
        import os
        from email.mime import base
        import transaction
        from repoze.sendmail._compat import b
        delivery = self._makeOne(self.maildir_path)

        non_ascii = b('LaPe\xc3\xb1a').decode('utf-8')
        fromaddr = non_ascii+' <*****@*****.**>'
        toaddrs = (non_ascii+' <*****@*****.**>',)
        message = base.MIMEBase('text', 'plain')
        message['From'] = fromaddr
        message['To'] = ','.join(toaddrs)

        delivery.send(fromaddr, toaddrs, message)
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'new')))
        transaction.commit()
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'new')))

        self.qp.send_messages()
        self.assertTrue(len(self.qp.mailer.sent_messages), 1)
        queued_fromaddr, queued_toaddrs, queued_message = (
            self.qp.mailer.sent_messages[0])
        self.assertEqual(queued_fromaddr, fromaddr)
        self.assertEqual(queued_toaddrs, toaddrs)
コード例 #11
0
def mailout(args, env):

    registry = env['registry']

    queue_path = registry.settings['mail_queue_path']

    mailer = SMTPMailer(
        hostname=args.server,
        port=args.port,
        username=args.username,
        password=args.password,
        no_tls=args.no_tls,
        force_tls=args.force_tls
    )
    qp = QueueProcessor(mailer, queue_path)
    qp.send_messages()
コード例 #12
0
 def setUp(self):
     from repoze.sendmail.queue import QueueProcessor
     self.qp = QueueProcessor()
     self.qp.maildir = MaildirStub('/foo/bar/baz')
     self.qp.mailer = MailerStub()
     self.qp.log = LoggerStub()
     self.dir = mkdtemp()
コード例 #13
0
 def setUp(self):
     import os
     import tempfile
     from repoze.sendmail.queue import QueueProcessor
     self.dir = tempfile.mkdtemp()
     self.maildir_path = os.path.join(self.dir, 'Maildir')
     self.qp = QueueProcessor(_makeMailerStub(), self.maildir_path)
コード例 #14
0
ファイル: mailout.py プロジェクト: disko/karl
def mailout(args, env):
    registry = env['registry']

    queue_path = registry.settings['mail_queue_path']
    mailout_throttle = registry.settings.get('mailout_throttle')

    mailer = SMTPMailer(
        hostname=args.server,
        port=args.port,
        username=args.username,
        password=args.password,
        no_tls=args.no_tls,
        force_tls=args.force_tls
    )
    qp = QueueProcessor(mailer, queue_path, ignore_transient=True)
    stats = MailoutStats(registry.settings.get('mailout_stats_dir'))

    # Instead of calling QueueProcessor.send_messages directly,
    # implement a throttle
    if mailout_throttle:
        int_mailout_throttle = int(mailout_throttle)
    else:
        int_mailout_throttle = 0
    counter = 0
    for filename in qp.maildir:
        counter += 1

        # If we have a throttle and we're over that limit, skip
        if mailout_throttle is not None and counter > int_mailout_throttle:
            continue

        if stats.mailout_stats_dir:
            # We're configured to do logging, so log
            with open(filename, 'r') as fp:
                parser = Parser()
                message = parser.parse(fp)
                stats.log(message)

        try:
            qp._send_message(filename)
        except smtplib.SMTPDataError, e:
            # probably an address verification error. Log and try later.
            log.info("Temporary error: %s" % str(e))
コード例 #15
0
ファイル: mailout.py プロジェクト: iotest3/new
def mailout(args, env):
    registry = env['registry']

    queue_path = registry.settings['mail_queue_path']
    mailout_throttle = registry.settings.get('mailout_throttle')

    mailer = SMTPMailer(hostname=args.server,
                        port=args.port,
                        username=args.username,
                        password=args.password,
                        no_tls=args.no_tls,
                        force_tls=args.force_tls)
    qp = QueueProcessor(mailer, queue_path, ignore_transient=True)
    stats = MailoutStats(registry.settings.get('mailout_stats_dir'))

    # Instead of calling QueueProcessor.send_messages directly,
    # implement a throttle
    if mailout_throttle:
        int_mailout_throttle = int(mailout_throttle)
    else:
        int_mailout_throttle = 0
    counter = 0
    for filename in qp.maildir:
        counter += 1

        # If we have a throttle and we're over that limit, skip
        if mailout_throttle is not None and counter > int_mailout_throttle:
            continue

        if stats.mailout_stats_dir:
            # We're configured to do logging, so log
            with open(filename, 'r') as fp:
                parser = Parser()
                message = parser.parse(fp)
                stats.log(message)

        try:
            qp._send_message(filename)
        except smtplib.SMTPDataError, e:
            # probably an address verification error. Log and try later.
            log.info("Temporary error: %s" % str(e))
コード例 #16
0
class TestQueueProcessor(TestCase):
    def setUp(self):
        from repoze.sendmail.queue import QueueProcessor
        self.qp = QueueProcessor(_makeMailerStub(), '/foo/bar/baz',
                                 MaildirStub)
        self.qp.log = LoggerStub()
        self.dir = mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.dir)

    def test_parseMessage(self):
        hdr = ('X-Actually-From: [email protected]\n'
               'X-Actually-To: [email protected], [email protected]\n')
        msg = ('Header: value\n' '\n' 'Body\n')
        f, t, m = self.qp._parseMessage(StringIO(u(hdr + msg)))
        self.assertEqual(f, '*****@*****.**')
        self.assertEqual(t, ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(m.as_string(), msg)

    def test_delivery(self):
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n') +
            b('X-Actually-To: [email protected], [email protected]\n') +
            b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()

        sent_message = self.qp.mailer.sent_messages[0]
        self.assertEqual(sent_message[0], '*****@*****.**')
        self.assertEqual(sent_message[1],
                         ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(sent_message[2].as_string(),
                         'Header: value\n\nBody\n')
        self.assertFalse(os.path.exists(self.filename), 'File exists')
        self.assertEqual(
            self.qp.log.infos,
            [('Mail from %s to %s sent.',
              ('*****@*****.**', '[email protected], [email protected]'), {})])

    def test_error_logging(self):
        self.qp.mailer = BrokenMailerStub()
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n') +
            b('X-Actually-To: [email protected], [email protected]\n') +
            b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()
        self.assertEqual(
            self.qp.log.errors,
            [('Error while sending mail from %s to %s.',
              ('*****@*****.**', '[email protected], [email protected]'), {
                  'exc_info': 1
              })])

    def test_error_logging_no_addrs(self):
        self.qp.mailer = BrokenMailerStub()
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()
        self.assertEqual(self.qp.log.errors,
                         [('Error while sending mail : %s ',
                           (self.filename, ), {
                               'exc_info': True
                           })])

    def test_smtp_response_error_transient(self):
        # Test a transient error
        self.qp.mailer = SMTPResponseExceptionMailerStub(451)
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n') +
            b('X-Actually-To: [email protected], [email protected]\n') +
            b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()

        # File must remail were it was, so it will be retried
        self.assertTrue(os.path.exists(self.filename))
        self.assertEqual(
            self.qp.log.errors,
            [('Error while sending mail from %s to %s.',
              ('*****@*****.**', '[email protected], [email protected]'), {
                  'exc_info': 1
              })])

    def test_smtp_response_error_permanent(self):
        # Test a permanent error
        self.qp.mailer = SMTPResponseExceptionMailerStub(550)
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n') +
            b('X-Actually-To: [email protected], [email protected]\n') +
            b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()

        # File must be moved aside
        self.assertFalse(os.path.exists(self.filename))
        self.assertTrue(
            os.path.exists(os.path.join(self.dir, '.rejected-message')))
        self.assertEqual(
            self.qp.log.errors,
            [('Discarding email from %s to %s due to a '
              'permanent error: %s',
              ('*****@*****.**', '[email protected], [email protected]',
               (550, 'Serious Error')), {})])

    def test_concurrent_delivery(self):
        # Attempt to send message
        self.filename = os.path.join(self.dir, 'message')

        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n') +
            b('X-Actually-To: [email protected], [email protected]\n') +
            b('Header: value\n\nBody\n'))
        temp.close()

        self.qp.maildir.files.append(self.filename)

        # Trick processor into thinking message is being delivered by
        # another process.
        head, tail = os.path.split(self.filename)
        tmp_filename = os.path.join(head, '.sending-' + tail)
        queue._os_link(self.filename, tmp_filename)
        try:
            self.qp.send_messages()

            self.assertEqual(self.qp.mailer.sent_messages, [])
            self.assertTrue(os.path.exists(self.filename),
                            'File does not exist')
            self.assertEqual(self.qp.log.infos, [])
        finally:
            os.unlink(tmp_filename)

    def test_concurrent_delivery_w_old_file(self):
        # Attempt to send message
        self.filename = os.path.join(self.dir, 'message')

        temp = open(self.filename, "w+b")
        temp.write(
            b('X-Actually-From: [email protected]\n'
              'X-Actually-To: [email protected], [email protected]\n'
              'Header: value\n\nBody\n'))
        temp.close()

        self.qp.maildir.files.append(self.filename)

        # Trick processor into thinking message is being delivered by
        # another process.
        head, tail = os.path.split(self.filename)
        tmp_filename = os.path.join(head, '.sending-' + tail)
        queue._os_link(self.filename, tmp_filename)
        os.utime(tmp_filename, (1, 1))  #mtime/utime 1970-01-01T00:00:01Z
        self.qp.send_messages()

        sent_message = self.qp.mailer.sent_messages[0]
        self.assertEqual(sent_message[0], '*****@*****.**')
        self.assertEqual(sent_message[1],
                         ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(sent_message[2].as_string(),
                         'Header: value\n\nBody\n')
        self.assertFalse(os.path.exists(self.filename), 'File still exists')
        self.assertEqual(
            self.qp.log.infos,
            [('Mail from %s to %s sent.',
              ('*****@*****.**', '[email protected], [email protected]'), {})])
        self.assertFalse(os.path.exists(tmp_filename))
コード例 #17
0
ファイル: mail_delivery.py プロジェクト: FvD/cobal.eportfolio
import logging

from repoze.bfg.settings import get_settings

from repoze.sendmail.delivery import QueuedMailDelivery
from repoze.sendmail.mailer import SMTPMailer
from repoze.sendmail.queue import QueueProcessor

settings = get_settings()
hostname = settings.get('mail_hostname', 'localhost')
port = settings.get('mail_port', 25)
username = settings.get('mail_username', None)
password = settings.get('mail_password', None)
no_tls = settings.get('mail_no_tls', None)
force_tls = settings.get('mail_force_tls', None)
mailer = SMTPMailer(hostname, port, username, password, no_tls, force_tls)

queue_path = settings.get('mail_queue_path', 'maildir')
queued_mail_delivery = QueuedMailDelivery(queue_path)

log = logging.getLogger('eportfolio')

qp = QueueProcessor(mailer, queue_path)
qp.log = log

def trigger_queued_delivery():
    try:
        qp.send_messages()
    except Exception, e:
        log.error(e)
コード例 #18
0
class TestQueueProcessor(TestCase):

    def setUp(self):
        from repoze.sendmail.queue import QueueProcessor
        self.qp = QueueProcessor(_makeMailerStub(), '/foo/bar/baz', MaildirStub)
        self.qp.log = LoggerStub()
        self.dir = mkdtemp()

    def tearDown(self):
        shutil.rmtree(self.dir)

    def test_parseMessage(self):
        hdr = ('X-Actually-From: [email protected]\n'
               'X-Actually-To: [email protected], [email protected]\n')
        msg = ('Header: value\n'
               '\n'
               'Body\n')
        f, t, m = self.qp._parseMessage(StringIO(u(hdr + msg)))
        self.assertEqual(f, '*****@*****.**')
        self.assertEqual(t, ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(m.as_string(), msg)

    def test_delivery(self):
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n')+
                   b('X-Actually-To: [email protected], [email protected]\n')+
                   b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()
        
        sent_message = self.qp.mailer.sent_messages[0]
        self.assertEqual(sent_message[0], '*****@*****.**')
        self.assertEqual(sent_message[1], 
                          ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(sent_message[2].as_string(), 
                          'Header: value\n\nBody\n')
        self.assertFalse(os.path.exists(self.filename), 'File exists')
        self.assertEqual(self.qp.log.infos,
                          [('Mail from %s to %s sent.',
                            ('*****@*****.**',
                             '[email protected], [email protected]'),
                            {})])

    def test_error_logging(self):
        self.qp.mailer = BrokenMailerStub()
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n')+
                   b('X-Actually-To: [email protected], [email protected]\n')+
                   b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()
        self.assertEqual(self.qp.log.errors,
                          [('Error while sending mail from %s to %s.',
                            ('*****@*****.**',
                             '[email protected], [email protected]'),
                            {'exc_info': 1})])

    def test_error_logging_no_addrs(self):
        self.qp.mailer = BrokenMailerStub()
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()
        self.assertEqual(self.qp.log.errors,
                          [('Error while sending mail : %s ',
                            (self.filename,),
                            {'exc_info': True})])

    def test_smtp_response_error_transient(self):
        # Test a transient error
        self.qp.mailer = SMTPResponseExceptionMailerStub(451)
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n')+
                   b('X-Actually-To: [email protected], [email protected]\n')+
                   b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()

        # File must remail were it was, so it will be retried
        self.assertTrue(os.path.exists(self.filename))
        self.assertEqual(self.qp.log.errors,
                          [('Error while sending mail from %s to %s.',
                            ('*****@*****.**',
                             '[email protected], [email protected]'),
                            {'exc_info': 1})])

    def test_smtp_response_error_permanent(self):
        # Test a permanent error
        self.qp.mailer = SMTPResponseExceptionMailerStub(550)
        self.filename = os.path.join(self.dir, 'message')
        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n')+
                   b('X-Actually-To: [email protected], [email protected]\n')+
                   b('Header: value\n\nBody\n'))
        temp.close()
        self.qp.maildir.files.append(self.filename)
        self.qp.send_messages()

        # File must be moved aside
        self.assertFalse(os.path.exists(self.filename))
        self.assertTrue(os.path.exists(os.path.join(self.dir,
                                                    '.rejected-message')))
        self.assertEqual(self.qp.log.errors,
                          [('Discarding email from %s to %s due to a '
                            'permanent error: %s',
                            ('*****@*****.**',
                             '[email protected], [email protected]',
                             (550, 'Serious Error')), {})])

    def test_concurrent_delivery(self):
        # Attempt to send message
        self.filename = os.path.join(self.dir, 'message')

        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n')+
                   b('X-Actually-To: [email protected], [email protected]\n')+
                   b('Header: value\n\nBody\n'))
        temp.close()

        self.qp.maildir.files.append(self.filename)

        # Trick processor into thinking message is being delivered by
        # another process.
        head, tail = os.path.split(self.filename)
        tmp_filename = os.path.join(head, '.sending-' + tail)
        queue._os_link(self.filename, tmp_filename)
        try:
            self.qp.send_messages()

            self.assertEqual(self.qp.mailer.sent_messages, [])
            self.assertTrue(os.path.exists(self.filename),
                            'File does not exist')
            self.assertEqual(self.qp.log.infos, [])
        finally:
            os.unlink(tmp_filename)

    def test_concurrent_delivery_w_old_file(self):
        # Attempt to send message
        self.filename = os.path.join(self.dir, 'message')

        temp = open(self.filename, "w+b")
        temp.write(b('X-Actually-From: [email protected]\n'
                     'X-Actually-To: [email protected], [email protected]\n'
                     'Header: value\n\nBody\n'))
        temp.close()

        self.qp.maildir.files.append(self.filename)

        # Trick processor into thinking message is being delivered by
        # another process.
        head, tail = os.path.split(self.filename)
        tmp_filename = os.path.join(head, '.sending-' + tail)
        queue._os_link(self.filename, tmp_filename)
        os.utime(tmp_filename, (1,1)) #mtime/utime 1970-01-01T00:00:01Z
        self.qp.send_messages()

        sent_message = self.qp.mailer.sent_messages[0]
        self.assertEqual(sent_message[0], '*****@*****.**')
        self.assertEqual(sent_message[1], 
                          ('*****@*****.**', '*****@*****.**'))
        self.assertEqual(sent_message[2].as_string(), 
                          'Header: value\n\nBody\n')
        self.assertFalse(os.path.exists(self.filename),
                         'File still exists')
        self.assertEqual(self.qp.log.infos,
                          [('Mail from %s to %s sent.',
                            ('*****@*****.**',
                             '[email protected], [email protected]'),
                            {})])
        self.assertFalse(os.path.exists(tmp_filename))