mirror of
https://github.com/caronc/apprise.git
synced 2025-07-01 06:51:03 +02:00
Refactored SSL/Auth handling of Emails (#774)
This commit is contained in:
@ -105,6 +105,12 @@ TEST_URLS = (
|
||||
('mailtos://user:pass@nuxref.com:567', {
|
||||
'instance': NotifyEmail,
|
||||
}),
|
||||
('mailto://user:pass@nuxref.com?mode=ssl', {
|
||||
# mailto:// with mode=ssl causes us to convert to ssl
|
||||
'instance': NotifyEmail,
|
||||
# Our expected url(privacy=True) startswith() response:
|
||||
'privacy_url': 'mailtos://user:****@nuxref.com',
|
||||
}),
|
||||
('mailto://user:pass@nuxref.com:567?format=html', {
|
||||
'instance': NotifyEmail,
|
||||
}),
|
||||
@ -913,6 +919,7 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert 'smtp=smtp-mail.outlook.com' in obj.url()
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
# The below switches the `name` with the `to` to verify the results
|
||||
@ -952,6 +959,11 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert _to[0] == 'user2@yahoo.com'
|
||||
assert _msg.split('\n')[-3] == 'test'
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
# the SMTP Server was ovr
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user'
|
||||
|
||||
assert obj.url().startswith(
|
||||
'mailtos://user:pass123@hotmail.com/user2%40yahoo.com')
|
||||
# Test that our template over-ride worked
|
||||
@ -961,11 +973,38 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert 'reply=' not in obj.url()
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
#
|
||||
# Test outlook/hotmail lookups
|
||||
#
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:pass123@hotmail.com')
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
assert isinstance(obj, NotifyEmail) is True
|
||||
assert obj.smtp_host == 'smtp-mail.outlook.com'
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user@hotmail.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:pass123@outlook.com')
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
@ -974,6 +1013,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user@outlook.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:pass123@outlook.com.au')
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
@ -982,6 +1039,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user@outlook.com.au'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
# Consisitency Checks
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://outlook.com?smtp=smtp.outlook.com'
|
||||
@ -994,6 +1069,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert obj1.secure_mode == 'starttls'
|
||||
assert obj1.port == 587
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj1.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'app.pw'
|
||||
assert user == 'user@outlook.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:app.pw@outlook.com')
|
||||
obj2 = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
@ -1004,6 +1097,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert obj2.secure_mode == obj1.secure_mode
|
||||
assert obj2.port == obj1.port
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj2.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'app.pw'
|
||||
assert user == 'user@outlook.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:pass123@live.com')
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
@ -1011,6 +1122,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user@live.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailtos://user:pass123@hotmail.com')
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
@ -1018,6 +1147,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass123'
|
||||
assert user == 'user@hotmail.com'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
#
|
||||
# Test Port Over-Riding
|
||||
#
|
||||
@ -1042,9 +1189,28 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
assert re.match(r'.*mode=ssl.*', obj.url()) is not None
|
||||
# No smtp= as the SMTP server is the same as the hostname in this case
|
||||
assert re.match(r'.*smtp=smtp.exmail.qq.com.*', obj.url()) is not None
|
||||
# URL is assembled based on provided user
|
||||
# URL is assembled based on provided user (:465 is dropped because it
|
||||
# is a default port when using xyz.cn)
|
||||
assert re.match(
|
||||
r'^mailtos://abc:password@xyz.cn:465/.*', obj.url()) is not None
|
||||
r'^mailtos://abc:password@xyz.cn/.*', obj.url()) is not None
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 1
|
||||
assert response.starttls.call_count == 0
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'password'
|
||||
assert user == 'abc'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
results = NotifyEmail.parse_url(
|
||||
"mailtos://abc:password@xyz.cn?"
|
||||
@ -1061,6 +1227,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# No entries in the reply_to
|
||||
assert not obj.reply_to
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 1
|
||||
assert response.starttls.call_count == 0
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'password'
|
||||
assert user == 'abc'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
#
|
||||
# Test Reply-To Email
|
||||
#
|
||||
@ -1078,6 +1262,24 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
# Test that our template over-ride worked
|
||||
assert 'reply=noreply%40example.com' in obj.url()
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass'
|
||||
assert user == 'user'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
#
|
||||
# Test Reply-To Email with Name Inline
|
||||
#
|
||||
@ -1094,3 +1296,67 @@ def test_plugin_email_url_parsing(mock_smtp, mock_smtp_ssl):
|
||||
'mailtos://user:pass@example.com')
|
||||
# Test that our template over-ride worked
|
||||
assert 'reply=Chris+%3Cnoreply%40example.ca%3E' in obj.url()
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 1
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert response.starttls.call_count == 1
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'pass'
|
||||
assert user == 'user'
|
||||
|
||||
mock_smtp.reset_mock()
|
||||
mock_smtp_ssl.reset_mock()
|
||||
response.reset_mock()
|
||||
|
||||
# Fast Mail Handling
|
||||
|
||||
# Test variations of username required to be an email address
|
||||
# user@example.com; we also test an over-ride port on a template driven
|
||||
# mailto:// entry
|
||||
results = NotifyEmail.parse_url(
|
||||
'mailto://fastmail.com/?to=hello@concordium-explorer.nl'
|
||||
'&user=joe@mydomain.nl&pass=abc123'
|
||||
'&from=Concordium Explorer Bot<bot@concordium-explorer.nl>')
|
||||
assert isinstance(results, dict)
|
||||
assert 'Concordium Explorer Bot<bot@concordium-explorer.nl>' == \
|
||||
results['from_addr']
|
||||
assert 'joe@mydomain.nl' == results['user']
|
||||
assert results['port'] is None
|
||||
assert 'fastmail.com' == results['host']
|
||||
assert 'abc123' == results['password']
|
||||
assert 'hello@concordium-explorer.nl' in results['targets']
|
||||
|
||||
obj = Apprise.instantiate(results, suppress_exceptions=False)
|
||||
assert isinstance(obj, NotifyEmail) is True
|
||||
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 0
|
||||
assert obj.notify("test") is True
|
||||
assert mock_smtp.call_count == 0
|
||||
assert mock_smtp_ssl.call_count == 1
|
||||
assert response.starttls.call_count == 0
|
||||
assert response.login.call_count == 1
|
||||
assert response.sendmail.call_count == 1
|
||||
# Store our Sent Arguments
|
||||
# Syntax is:
|
||||
# sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())
|
||||
# [0] [1] [2]
|
||||
_from = response.sendmail.call_args[0][0]
|
||||
_to = response.sendmail.call_args[0][1]
|
||||
_msg = response.sendmail.call_args[0][2]
|
||||
assert _from == 'bot@concordium-explorer.nl'
|
||||
assert isinstance(_to, list)
|
||||
assert len(_to) == 1
|
||||
assert _to[0] == 'hello@concordium-explorer.nl'
|
||||
assert _msg.split('\n')[-3] == 'test'
|
||||
|
||||
user, pw = response.login.call_args[0]
|
||||
assert pw == 'abc123'
|
||||
assert user == 'joe@mydomain.nl'
|
||||
|
Reference in New Issue
Block a user