summaryrefslogtreecommitdiff
path: root/ssmain/email.py
blob: 090f2fafe009e645e36594fa9e90c05431859c01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
1#    Society Self-Service
2#    Copyright © 2018-2020  Yingtong Li (RunasSudo)
3#
4#    This program is free software: you can redistribute it and/or modify
5#    it under the terms of the GNU Affero General Public License as published by
6#    the Free Software Foundation, either version 3 of the License, or
7#    (at your option) any later version.
8#
9#    This program is distributed in the hope that it will be useful,
10#    but WITHOUT ANY WARRANTY; without even the implied warranty of
11#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12#    GNU Affero General Public License for more details.
13#
14#    You should have received a copy of the GNU Affero General Public License
15#    along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17import boto3
18from botocore.exceptions import ClientError
19import premailer
20
21from django.conf import settings
22from django.template import loader
23from jinja2 import Markup
24
25from selfserv.mdx_urlize import UrlizeExtension
26
27import logging
28import markdown
29
30# Debugging
31import subprocess
32import tempfile
33import time
34
35class Emailer:
36	def __init__(self):
37		self.client = boto3.client('ses', aws_access_key_id=settings.AWS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET, region_name=settings.AWS_REGION)
38		self.template = loader.get_template('ssmain/email/rendered.html')
39	
40	def markdown(self, x):
41		return markdown.markdown(x, extensions=[UrlizeExtension(), 'fenced_code'])
42	
43	def boto3_send(self, *args, **kwargs):
44		for i in range(0, 10):
45			try:
46				self.client.send_email(*args, **kwargs)
47				return
48			except ClientError as e:
49				if e['Error']['Code'] == 'Throttling' and e['Error']['Message'] == 'Maximum sending rate exceeded.':
50					wait_time = max(10*(2**i), 5000)
51					#self.stdout.write(self.style.NOTICE('Reached maximum sending rate, waiting {} ms'.format(wait_time)))
52					time.sleep(wait_time/1000)
53				else:
54					raise e
55		raise Exception('Reached maximum number of retries')
56	
57	def send_raw_mail(self, recipients, subject, content_txt, content_html):
58		if settings.EMAIL_DEBUG:
59			with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', suffix='.eml') as f:
60				print('Subject:' + subject + '\nContent-Type: multipart/alternative; boundary=boundary\n\n--boundary\nContent-Type: text/html; charset=utf-8\n\n' + content_html + '\n--boundary\nContent-Type: text/plain; charset=utf-8\n\n' + content_txt + '\n--boundary', file=f)
61				subprocess.run(['thunderbird', f.name])
62				time.sleep(5)
63		else:
64			self.boto3_send(
65				Destination={
66					'ToAddresses': recipients,
67				},
68				Message={
69					'Body': {
70						'Html': {
71							'Charset': 'utf-8',
72							'Data': content_html,
73						},
74						'Text': {
75							'Charset': 'utf-8',
76							'Data': content_txt,
77						},
78					},
79					'Subject': {
80						'Charset': 'utf-8',
81						'Data': subject,
82					},
83				},
84				Source='{} <{}>'.format(settings.ORG_NAME, settings.AWS_SENDER_EMAIL),
85			)
86	
87	def render_mail(self, template_loc, params={}):
88		params['baseurl'] = 'https://' + settings.ALLOWED_HOSTS[0]
89		
90		template = loader.get_template(template_loc)
91		content_txt = template.render(params)
92		
93		content_markdown = self.markdown(content_txt)
94		content_html = self.template.render({'email_content': Markup(content_markdown)})
95		
96		content_html = premailer.Premailer(content_html, cssutils_logging_level=logging.ERROR, strip_important=False).transform()
97		
98		return content_txt, content_html
99	
100	def send_mail(self, recipients, subject, template_loc, params):
101		content_txt, content_html = self.render_mail(template_loc, params)
102		self.send_raw_mail(recipients, subject, content_txt, content_html)
Contact (issues, pull requests, etc.) at git@yingtongli.me. Generated by cgit.