Skip to content

Commit 0b0c848

Browse files
committed
Fixes #12 - migrated to sendgrid for email handling.
1 parent 089ba8b commit 0b0c848

File tree

4 files changed

+152
-52
lines changed

4 files changed

+152
-52
lines changed
File renamed without changes.

logic.py

+149-49
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
import pandas as pd
1111
import itsdangerous
12-
import mandrill
12+
import sendgrid
13+
1314
import bcrypt
1415
from sqlalchemy import create_engine
1516
from sqlalchemy.exc import IntegrityError
@@ -664,7 +665,7 @@ def mark_batch_read(batch, user):
664665
Discussion
665666
"""
666667
_USER_FB_ITSD = itsdangerous.URLSafeSerializer(os.environ['ITSD_KEY'])
667-
_MANDRILL = mandrill.Mandrill(os.environ['MANDRILL_API_KEY'])
668+
_SENDGRID = sendgrid.SendGridAPIClient(apikey=os.environ['SENDGRID_API_KEY'])
668669
_EMAIL_FROM = os.environ['EMAIL_FROM']
669670
_WEB_HOST = os.environ['WEB_HOST']
670671

@@ -710,14 +711,25 @@ def add_to_discussion(userid, proposal, body, feedback=False, name=None):
710711
edit_url = 'https://us.pycon.org/2016/proposals/{}/'.format(proposal)
711712
rendered = email.render(proposal=full_proposal, body=body,
712713
url=url, edit_url=edit_url)
713-
msg = {'text': rendered,
714-
'subject': 'Feedback on Your PyCon Talk Proposal',
715-
'from_email': _EMAIL_FROM,
716-
'from_name': 'PyCon Program Committee',
717-
'to': [{'email':to}],
718-
'auto_html':False,}
719-
l('filter_email_sent', api_result=_MANDRILL.messages.send(msg),
720-
to=to)
714+
msg = {
715+
"personalizations": [
716+
{
717+
"to": [{"email": to}],
718+
"subject": 'Feedback on Your PyCon Talk Proposal',
719+
}
720+
],
721+
"from": {
722+
"email": _EMAIL_FROM,
723+
"name": "PyCon Program Committee"
724+
},
725+
"content": [
726+
{
727+
"type": "text/plain",
728+
"value": rendered,
729+
}
730+
]
731+
}
732+
l('filter_email_sent', api_result=_SENDGRID.client.mail.send.post(request_body=msg), to=to)
721733

722734

723735
def mark_read(userid, proposal):
@@ -769,12 +781,26 @@ def send_login_email(email):
769781
url = 'http://{}/user/login/{}/'.format(_WEB_HOST, key)
770782
body = body.render(url=url)
771783

772-
msg = {'text':body,
773-
'subject': 'PyCon Program Committee Password Reset',
774-
'from_email':'[email protected]',
775-
'from_name':'Ned Jackson Lovely',
776-
'to':[{'email':user.email}]}
777-
_MANDRILL.messages.send(msg)
784+
msg = {
785+
"personalizations": [
786+
{
787+
"to": [{"email": user.email}],
788+
"subject": 'PyCon Program Committee Password Reset',
789+
}
790+
],
791+
"from": {
792+
"email": "[email protected]",
793+
"name": "Ned Jackson Lovely"
794+
},
795+
"content": [
796+
{
797+
"type": "text/plain",
798+
"value": body,
799+
}
800+
]
801+
}
802+
803+
_SENDGRID.client.mail.send.post(request_body=msg)
778804
l('successful_pw_reset_request', email=email, id=user.id)
779805
return True
780806

@@ -788,23 +814,53 @@ def test_login_string(s):
788814

789815
def email_approved(id):
790816
user = get_user(id)
791-
msg = {'text': _JINJA.get_template('email/welcome_user.txt').render(),
792-
'subject': 'Welcome to the Program Committee Web App!',
793-
'from_email': '[email protected]',
794-
'from_name':'Ned Jackson Lovely',
795-
'to':[{'email':user.email}]
796-
+ [{'email':x, 'type':'cc'} for x in _ADMIN_EMAILS]}
797-
_MANDRILL.messages.send(msg)
817+
818+
msg = {
819+
"personalizations": [
820+
{
821+
"to": [{"email": user.email}],
822+
"subject": 'Welcome to the Program Committee Web App!',
823+
"cc": [{"email": x} for x in _ADMIN_EMAILS],
824+
}
825+
],
826+
"from": {
827+
"email": "[email protected]",
828+
"name": "Ned Jackson Lovely"
829+
},
830+
"content": [
831+
{
832+
"type": "text/plain",
833+
"value": _JINJA.get_template('email/welcome_user.txt').render(),
834+
}
835+
]
836+
}
837+
838+
_SENDGRID.client.mail.send.post(request_body=msg)
798839

799840
def email_new_user_pending(email, name):
800841
body = _JINJA.get_template('email/new_user_pending.txt').render(name=name,
801842
email=email)
802-
msg = {'text': body,
803-
'subject': 'New Progcom User',
804-
'from_email': '[email protected]',
805-
'from_name':'PyCon Program Committee Robot',
806-
'to':[{'email':x} for x in _ADMIN_EMAILS]}
807-
_MANDRILL.messages.send(msg)
843+
844+
msg = {
845+
"personalizations": [
846+
{
847+
"to": [{"email": x} for x in _ADMIN_EMAILS],
848+
"subject": 'New Progcom User',
849+
}
850+
],
851+
"from": {
852+
"email": "[email protected]",
853+
"name": "PyCon Program Committee Robot"
854+
},
855+
"content": [
856+
{
857+
"type": "text/plain",
858+
"value": body,
859+
}
860+
]
861+
}
862+
863+
_SENDGRID.client.mail.send.post(request_body=msg)
808864

809865
def send_weekly_update():
810866
body = _JINJA.get_template('email/weekly_email.txt')
@@ -813,12 +869,28 @@ def send_weekly_update():
813869
votes_last_week=votes_last_week(),
814870
active_discussions=active_discussions(),
815871
screening_progress=screening_progress())
816-
msg = {'text':body,
817-
'subject':'Weekly Program Committee Status',
818-
'from_email': '[email protected]',
819-
'from_name': 'PyCon Program Committee Robot',
820-
'to':[{'email':'[email protected]'}]}
821-
_MANDRILL.messages.send(msg)
872+
873+
msg = {
874+
"personalizations": [
875+
{
876+
"to": [{"email": "[email protected]"}],
877+
"subject": 'Weekly Program Committee Status',
878+
}
879+
],
880+
"from": {
881+
"email": "[email protected]",
882+
"name": "PyCon Program Committee Robot"
883+
},
884+
"content": [
885+
{
886+
"type": "text/plain",
887+
"value": body,
888+
}
889+
]
890+
}
891+
892+
_SENDGRID.client.mail.send.post(request_body=msg)
893+
822894

823895
"""
824896
Experimental Topic Grouping
@@ -988,13 +1060,27 @@ def send_emails():
9881060
continue
9891061
if not p.accepted:
9901062
text = decline.render(name=name, title=p.title)
991-
msg = {'text':text,
992-
'subject': u'PyCon 2016: Proposal Decision -- '+p.title,
993-
'from_email': '[email protected]',
994-
'from_name': 'Ned Jackson Lovely',
995-
'to':[{'email':email}],
996-
'auto_html':False}
997-
print _MANDRILL.messages.send(msg)
1063+
1064+
msg = {
1065+
"personalizations": [
1066+
{
1067+
"to": [{"email": email}],
1068+
"subject": u'PyCon 2017: Proposal Decision -- '+p.title,
1069+
}
1070+
],
1071+
"from": {
1072+
"email": "[email protected]",
1073+
"name": "Ned Jackson Lovely"
1074+
},
1075+
"content": [
1076+
{
1077+
"type": "text/plain",
1078+
"value": text,
1079+
}
1080+
]
1081+
}
1082+
1083+
print _SENDGRID.client.mail.send.post(request_body=msg)
9981084
declined +=1
9991085
continue
10001086
q = '''INSERT INTO confirmations (proposal, email)
@@ -1003,13 +1089,27 @@ def send_emails():
10031089
key = _CONFIRMATION_ITSD.dumps(id)
10041090
url = 'http://{}/confirmation/{}/'.format(_WEB_HOST, key)
10051091
text = accepted.render(name=name, title=p.title, url=url)
1006-
msg = {'text': text,
1007-
'subject': 'PyCon 2016: Talk Acceptance -- '+p.title,
1008-
'from_email': '[email protected]',
1009-
'from_name': 'Ned Jackson Lovely',
1010-
'to':[{'email':email}],
1011-
'auto_html':False}
1012-
print _MANDRILL.messages.send(msg)
1092+
msg = {
1093+
"personalizations": [
1094+
{
1095+
"to": [{"email": email}],
1096+
"subject": u'PyCon 2017: Talk Acceptance -- '+p.title,
1097+
}
1098+
],
1099+
"from": {
1100+
"email": "[email protected]",
1101+
"name": "Ned Jackson Lovely"
1102+
},
1103+
"content": [
1104+
{
1105+
"type": "text/plain",
1106+
"value": text,
1107+
}
1108+
]
1109+
}
1110+
1111+
print _SENDGRID.client.mail.send.post(request_body=msg)
1112+
10131113
acceptance +=1
10141114
print 'Declined: {}'.format(declined)
10151115
print 'Accepted: {}'.format(acceptance)

logic_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
import logic as l
88

9-
l._M_OLD = l._MANDRILL
10-
l._MANDRILL = mock.Mock()
9+
l._S_OLD = l._SENDGRID
10+
l._SENDGRID = mock.Mock()
1111

1212

1313
@pytest.fixture(autouse=True)

requirements.pip

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ sqlalchemy
33
bcrypt
44
psycopg2
55
itsdangerous
6-
mandrill
6+
sendgrid
77
bleach
88
markdown2
99
simplejson

0 commit comments

Comments
 (0)