def test_no_dry_run(mock_getpass, mock_SMTP_SSL, tmp_path): """Verify --no-dry-run calls SMTP sendmail().""" config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = open-smtp.example.com port = 465 security = SSL/TLS username = admin """)) sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u""" TO: [email protected] SUBJECT: Testing mailmerge FROM: [email protected] Hello world """) # Mock the password entry mock_getpass.return_value = "password" # Send a message sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify function calls for password and sendmail() assert mock_getpass.call_count == 1 smtp = mock_SMTP_SSL.return_value.__enter__.return_value assert smtp.sendmail.call_count == 1
def test_socket_error(mock_getpass, mock_SMTP_SSL, tmp_path): """Failed socket connection.""" # Config for SSL SMTP server config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = smtp.gmail.com port = 465 security = SSL/TLS username = awdeorio """)) # Simple template sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u"Hello world") # Mock the password entry mock_getpass.return_value = "password" # Configure SMTP_SSL constructor to raise an exception mock_SMTP_SSL.return_value.__enter__ = mock.Mock( side_effect=socket.error("Dummy error message") ) # Send a message with pytest.raises(MailmergeError) as err: sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify exception string assert "Dummy error message" in str(err.value)
def test_dry_run(mock_getpass, mock_SMTP, tmp_path): """Verify no sendmail() calls when dry_run=True.""" config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = open-smtp.example.com port = 25 security = Never """)) sendmail_client = SendmailClient( config_path, dry_run=True, ) message = email.message_from_string(u""" TO: [email protected] SUBJECT: Testing mailmerge FROM: [email protected] Hello world """) sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify SMTP wasn't called and password wasn't used assert mock_getpass.call_count == 0 smtp = mock_SMTP.return_value.__enter__.return_value assert smtp.sendmail.call_count == 0
def test_security_ssl(mock_getpass, mock_SMTP_SSL, mock_SMTP, tmp_path): """Verify open (Never) security configuration.""" # Config for SSL SMTP server config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = smtp.mail.umich.edu port = 465 security = SSL/TLS username = YOUR_USERNAME_HERE """)) # Simple template sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u"Hello world") # Mock the password entry mock_getpass.return_value = "password" # Send a message sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify SMTP library calls assert mock_getpass.call_count == 1 assert mock_SMTP.call_count == 0 assert mock_SMTP_SSL.call_count == 1 smtp = mock_SMTP_SSL.return_value.__enter__.return_value assert smtp.ehlo.call_count == 0 assert smtp.starttls.call_count == 0 assert smtp.login.call_count == 1 assert smtp.sendmail.call_count == 1
def test_smtp(mock_SMTP, tmp_path): """Verify SMTP library calls.""" config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = open-smtp.example.com port = 25 """)) sendmail_client = SendmailClient( config_path, dry_run=False, ) message = email.message_from_string(u""" TO: [email protected] SUBJECT: Testing mailmerge FROM: [email protected] Hello world """) sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Mock smtp object with function calls recorded smtp = mock_SMTP.return_value.__enter__.return_value assert smtp.sendmail.call_count == 1
def test_security_open_legacy(mock_SMTP, tmp_path): """Verify legacy "security = Never" configuration.""" # Config SMTP server with "security = Never" legacy option config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = open-smtp.example.com port = 25 security = Never """)) # Simple template sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u"Hello world") # Send a message sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify SMTP library calls smtp = mock_SMTP.return_value.__enter__.return_value assert smtp.sendmail.call_count == 1
def test_security_open(mock_getpass, mock_SMTP_SSL, mock_SMTP, tmp_path): """Verify open (Never) security configuration.""" # Config for no security SMTP server config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = open-smtp.example.com port = 25 """)) # Simple template sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u"Hello world") # Send a message sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify SMTP library calls assert mock_getpass.call_count == 0 assert mock_SMTP.call_count == 1 assert mock_SMTP_SSL.call_count == 0 smtp = mock_SMTP.return_value.__enter__.return_value assert smtp.sendmail.call_count == 1 assert smtp.login.call_count == 0
def test_smtp_login_error(mock_getpass, mock_SMTP_SSL, tmp_path): """Login failure.""" # Config for SSL SMTP server config_path = tmp_path/"server.conf" config_path.write_text(textwrap.dedent(u"""\ [smtp_server] host = smtp.gmail.com port = 465 security = SSL/TLS username = awdeorio """)) # Simple template sendmail_client = SendmailClient(config_path, dry_run=False) message = email.message_from_string(u"Hello world") # Mock the password entry mock_getpass.return_value = "password" # Configure SMTP login() to raise an exception mock_SMTP_SSL.return_value.__enter__.return_value.login = mock.Mock( side_effect=smtplib.SMTPAuthenticationError( code=535, msg=( "5.7.8 Username and Password not accepted. Learn more at " "5.7.8 https://support.google.com/mail/?p=BadCredentials " "xyzxyz.32 - gsmtp" ) ) ) # Send a message with pytest.raises(MailmergeError) as err: sendmail_client.sendmail( sender="*****@*****.**", recipients=["*****@*****.**"], message=message, ) # Verify exception string assert "smtp.gmail.com:465 failed to authenticate user 'awdeorio'" in\ str(err.value) assert "535" in str(err.value) assert ( "5.7.8 Username and Password not accepted. Learn more at " "5.7.8 https://support.google.com/mail/?p=BadCredentials " "xyzxyz.32 - gsmtp" ) in str(err.value)
def render(self, context): """Return rendered message object.""" try: raw_message = self.template.render(context) except jinja2.exceptions.TemplateError as err: raise MailmergeError("{}: {}".format(self.template_path, err)) self._message = email.message_from_string(raw_message) self._transform_encoding(raw_message) self._transform_recipients() self._transform_markdown() self._transform_attachments() self._message.__setitem__('Date', email.utils.formatdate()) assert self._sender assert self._recipients assert self._message return self._sender, self._recipients, self._message