diff --git a/.gitignore b/.gitignore index 804fef4..5180805 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ dummy_project/* .tox/ messages *.sqlite3 +venv/* +.idea/ diff --git a/django_mailbox/management/commands/sendmail.py b/django_mailbox/management/commands/sendmail.py new file mode 100644 index 0000000..87fdf57 --- /dev/null +++ b/django_mailbox/management/commands/sendmail.py @@ -0,0 +1,26 @@ +from django.core.management.base import BaseCommand + +from django_mailbox.models import Mailbox + + +class Command(BaseCommand): + help = 'Sends an e-mail to specified recipient' + + def add_arguments(self, parser): + parser.add_argument('from', type=int, help='ID (pk) for the mailbox you want to use to send an e-mail') + parser.add_argument('to', type=str, help='E-mail address of recipient') + parser.add_argument('subject', type=str, help='Subject of letter') + parser.add_argument('body', type=str, help='Message') + + def handle(self, *args, **options): + from_email = options.get('from') + to = options.get('to') + subject = options.get('subject') + body = options.get('body') + + mailbox = Mailbox.objects.get(pk=from_email) + self.stdout.write(self.style.WARNING("-"*36 + "\nFrom: %s \nTo: %s \nSubject: %s \nMessage: %s \n" % + (mailbox.from_email, + to, subject, body) + '-'*36)) + if mailbox.send_mail(subject, to, body): + self.stdout.write(self.style.SUCCESS('The letter is sent.')) diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 9f7ffc2..b4ee357 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -34,7 +34,7 @@ from django_mailbox import utils from django_mailbox.signals import message_received from django_mailbox.transports import Pop3Transport, ImapTransport, \ MaildirTransport, MboxTransport, BabylTransport, MHTransport, \ - MMDFTransport, GmailImapTransport + MMDFTransport, GmailImapTransport, SMTPTransport logger = logging.getLogger(__name__) @@ -213,6 +213,14 @@ class Mailbox(models.Model): ssl=self.use_ssl ) conn.connect(self.username, self.password) + elif self.type == 'smtp': + conn = SMTPTransport( + self.location, + port=self.port if self.port else None, + ssl=self.use_ssl, + tls=self.use_tls + ) + conn.connect(self.username, self.password) elif self.type == 'maildir': conn = MaildirTransport(self.location) elif self.type == 'mbox': @@ -420,6 +428,14 @@ class Mailbox(models.Model): else: self.save() + def send_mail(self, subject, to, body): + connection = self.get_connection() + if not connection: + return + connection.connect(self.username, self.password) + connection.send_message(subject, body, self.username, to) + return 'Success' + def __str__(self): return self.name @@ -821,3 +837,4 @@ class MessageAttachment(models.Model): class Meta: verbose_name = _('Message attachment') verbose_name_plural = _('Message attachments') + diff --git a/django_mailbox/tests/test_transports.py b/django_mailbox/tests/test_transports.py index 1d3c68f..a679bd6 100644 --- a/django_mailbox/tests/test_transports.py +++ b/django_mailbox/tests/test_transports.py @@ -4,7 +4,7 @@ import six from django.test.utils import override_settings from django_mailbox.tests.base import EmailMessageTestCase, get_email_as_text -from django_mailbox.transports import ImapTransport, Pop3Transport +from django_mailbox.transports import ImapTransport, Pop3Transport, SMTPTransport FAKE_UID_SEARCH_ANSWER = ( 'OK', @@ -168,3 +168,25 @@ class TestPop3Transport(EmailMessageTestCase): expected_message = self._get_email_object('generic_message.eml') self.assertEqual(expected_message, actual_message) + + +class TestSMTPTransport(EmailMessageTestCase): + class TestSMTPTransport(EmailMessageTestCase): + def setUp(self): + self.arbitrary_hostname = '' + self.arbitrary_port = 465 + self.ssl = True + self.transport = SMTPTransport( + self.arbitrary_hostname, + self.arbitrary_port, + self.ssl + ) + + def test_sending_messages(self): + with mock.patch('SMTPTransport') as mock_smtp: + from_address = 'from@domain.com' + to_address = 'to@domain.com' + + smtp = mock_smtp('smtp.domain.com') + + smtp.send_message(from_address, [to_address], 'subject', 'message') diff --git a/django_mailbox/transports/__init__.py b/django_mailbox/transports/__init__.py index 7aeef95..f2cf3e4 100644 --- a/django_mailbox/transports/__init__.py +++ b/django_mailbox/transports/__init__.py @@ -8,3 +8,4 @@ from django_mailbox.transports.babyl import BabylTransport from django_mailbox.transports.mh import MHTransport from django_mailbox.transports.mmdf import MMDFTransport from django_mailbox.transports.gmail import GmailImapTransport +from django_mailbox.transports.smtp import SMTPTransport diff --git a/django_mailbox/transports/smtp.py b/django_mailbox/transports/smtp.py new file mode 100644 index 0000000..8a80225 --- /dev/null +++ b/django_mailbox/transports/smtp.py @@ -0,0 +1,51 @@ +from smtplib import SMTP, SMTP_SSL + +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.image import MIMEImage + +from django_mailbox.transports.base import EmailTransport + + +class SMTPTransport(EmailTransport): + def __init__(self, hostname, port=None, + ssl=False, tls=False): + self.hostname = hostname + self.port = port + self.tls = tls + self.server = None + + if ssl: + self.transport = SMTP_SSL + if not self.port: + self.port = 465 + else: + self.transport = SMTP + if not self.port: + self.port = 25 + + def connect(self, username, password): + self.server = self.transport(self.hostname, self.port) + if self.tls: + self.server.starttls() + + _ = self.server.login(user=username, password=password) + + def send_message(self, subject, message, from_email, recipient_list, img=None, html=False): + msg = MIMEMultipart() + + msg_text = MIMEText(message, 'plain' if not html else 'html') + + if img: + with open(img, 'rb') as fp: + msg_img = MIMEImage(fp.read()) + msg.attach(msg_img) + + msg.attach(msg_text) + + msg['From'] = from_email + msg['To'] = recipient_list + msg['Subject'] = subject + + self.server.sendmail(msg['From'], msg['To'], msg.as_string()) + self.server.quit()