1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
import smtplib |
3
|
|
|
from email.header import Header |
4
|
|
|
from email.mime.multipart import MIMEMultipart |
5
|
|
|
from email.mime.text import MIMEText |
6
|
|
|
from email.mime.base import MIMEBase |
7
|
|
|
from email import encoders |
8
|
|
|
|
9
|
|
|
from pyramid.compat import text_ |
10
|
|
|
|
11
|
|
|
|
12
|
|
|
class SMTPClient: |
13
|
|
|
def __init__(self, smpt, sender): |
14
|
|
|
''' |
15
|
|
|
:param smtp: Simple Mail Transfer Protocol (SMTP) to send mails |
16
|
|
|
:param sender: Sender of the mail |
17
|
|
|
''' |
18
|
|
|
self.smtp = smpt |
19
|
|
|
self.sender = sender |
20
|
|
|
|
21
|
|
|
@property |
22
|
|
|
def smtp_obj(self): # pragma no cover |
23
|
|
|
return smtplib.SMTP(self.smtp) |
24
|
|
|
|
25
|
|
|
def send_mail(self, receivers, subject, message_plain, message_html=None, cc=None, bcc=None, files=None): |
26
|
|
|
''' |
27
|
|
|
|
28
|
|
|
send an email |
29
|
|
|
|
30
|
|
|
:param receivers: Receivers (list) |
31
|
|
|
:param subject: Email subject |
32
|
|
|
:param message_plain: Email message (plain text) |
33
|
|
|
:param message_html: Email message (html version) |
34
|
|
|
:param cc: carbon copy (list) |
35
|
|
|
:param bcc: blind carbon copy (list) |
36
|
|
|
:param files: array for attachments with {'name': filename, 'data': binary attachmentdata} |
37
|
|
|
''' |
38
|
|
|
msg = MIMEMultipart('alternative') |
39
|
|
|
msg['Subject'] = Header(subject, "utf-8") |
40
|
|
|
msg['From'] = Header(text_(self.sender), "utf-8") |
41
|
|
|
msg['To'] = Header(text_('; '.join(receivers)), "utf-8") |
42
|
|
|
if cc: |
43
|
|
|
msg['CC'] = Header(text_('; '.join(cc)), "utf-8") |
44
|
|
|
else: |
45
|
|
|
cc = [] |
46
|
|
|
if bcc: |
47
|
|
|
msg['BCC'] = Header(text_('; '.join(bcc)), "utf-8") |
48
|
|
|
else: |
49
|
|
|
bcc = [] |
50
|
|
|
if message_html: |
51
|
|
|
part1 = MIMEText(message_plain, 'plain', _charset="UTF-8") |
52
|
|
|
part2 = MIMEText(message_html, 'html', _charset="UTF-8") |
53
|
|
|
|
54
|
|
|
# Attach parts into message container. |
55
|
|
|
# According to RFC 2046, the last part of a multipart message, in this case |
56
|
|
|
# the HTML message, is best and preferred. |
57
|
|
|
msg.attach(part1) |
58
|
|
|
msg.attach(part2) |
59
|
|
|
else: |
60
|
|
|
part1 = MIMEText(message_plain, 'plain', _charset="UTF-8") |
61
|
|
|
msg.attach(part1) |
62
|
|
|
if files: |
63
|
|
|
for f in files or []: |
64
|
|
|
maintype, subtype = f['mime'].split("/", 1) |
65
|
|
|
attachment = MIMEBase(maintype, subtype) |
66
|
|
|
attachment.set_payload(f['data']) |
67
|
|
|
encoders.encode_base64(attachment) |
68
|
|
|
attachment.add_header("Content-Disposition", "attachment", filename=f['name']) |
69
|
|
|
msg.attach(attachment) |
70
|
|
|
self.smtp_obj.sendmail(self.sender, receivers + cc + bcc, msg.as_string()) |
71
|
|
|
|