def send(self, signal: Signal) -> None: if not isinstance(signal, Signal): raise TypeError(type(signal)) if not isinstance(signal, Message): raise SignalTypeNotSupported(type(signal)) meta_data = signal.meta_data content = signal.content if isinstance(content, str): content_string = content content = MIMEPart() content.set_payload(content_string) if meta_data.room: raise OperationNotSupported( "Chat rooms are not supported for email sessions.") if meta_data.identifier: content['message-id'] = meta_data.identifier if meta_data.origin: content['from'] = meta_data.origin if meta_data.addressees: content['to'] = ';'.join(meta_data.addressees) if meta_data.visible_to: content['cc'] = ';'.join(meta_data.visible_to) if meta_data.response_to: content['reply-to'] = meta_data.response_to with self._smtp_factory() as connection: connection.send_message(content)
def _wrap_message(milter): attachment = MIMEPart(policy=SMTPUTF8) attachment.set_content(milter.msg.as_bytes(), maintype="plain", subtype="text", disposition="attachment", filename=f"{milter.qid}.eml", params={"name": f"{milter.qid}.eml"}) milter.msg.clear_content() milter.msg.set_content( "Please see the original email attached.") milter.msg.add_alternative( "<html><body>Please see the original email attached.</body></html>", subtype="html") milter.msg.make_mixed() milter.msg.attach(attachment)
def attach_stream(self, stream: IOBase, file_name: str) -> Message: """Read a stream into an attachment and attach to this message. This method returns the object, so you can chain it like:: msg.attach(file_handle, "test.txt").attach(byte_stream, "test.bin") Args: stream (IOBase): The stream to read from. file_name (str): The name of the file, used for MIME type identification. Returns: Message: this Message, for chaining. """ mime_type = mimetypes.guess_type(file_name)[0] # it's possible we get a file that doesn't have a mime type, like a # Linux executable, or a mach-o file - in that case just set it # to octet-stream as a generic stream of bytes if mime_type is None: main_type, sub_type = ("application", "octet-stream") else: main_type, sub_type = mime_type.split("/") attachment = MIMEPart() # we need special handling for set_content with datatype of str, as # for some reason this method doesn't like 'maintype' # see: https://docs.python.org/3/library/ # email.contentmanager.html#email.contentmanager.set_content content_args = {"subtype": sub_type} if main_type != "text": content_args["maintype"] = main_type file_name = path.basename(file_name) attachment.set_content(stream.read(), filename=file_name, disposition="attachment", **content_args) self.attachments.append(attachment) return self
def write_html(output_dir: str, transaction_id: str, part: MIMEPart) -> None: """Write the HTML part of an email to disk. Args: output_dir (str): The directory to write the file to. transaction_id (str): The transaction ID of the email. part (MIMEPart): The MIME part representing the attachment. """ filename = f"{transaction_id}_html.html" logging.info(f" Writing email body '{filename}'") with open(join(output_dir, filename), "w") as body_file: # the replace is due to weird formatting of HTML in MIME body_file.write(part.get_payload().replace("=\n", ""))
def write_attachment(output_dir: str, transaction_id: str, part: MIMEPart) -> None: """Write an attachment file to disk. Args: output_dir (str): The directory to write the file to. transaction_id (str): The transaction ID of the email. part (MIMEPart): The MIME part representing the attachment. """ filename = f"{transaction_id}_{part.get_filename()}" logging.info(f" Writing attachment '{filename}'") with open(join(output_dir, filename), "wb") as attachment_file: decoded = base64.b64decode(part.get_payload()) attachment_file.write(decoded)
def new(): return MIMEPart(policy)
def test_parts(gm_client, latest, load_email): gm_client.add_emails([{'raw': binary('').as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' assert m['body_txt'] is None raw = '<?xml version="1.0" encoding="UTF-8"?>' gm_client.add_emails([{'raw': binary(raw, 'text/html').as_bytes()}]) m = latest(parsed=True) assert m['meta']['preview'] == '' assert m['body'] == '' gm_client.add_emails([{'raw': binary(' a b\n c d').as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == ' a b c d' assert m['body'] == '<p> a b<br> c d</p>' raw = ( '<p>' '<img data-style="test" />' '<img data-src="test" />' '<img data-style="color:blue" style="color:red" />' '<img src="test" />' '</p>' ) gm_client.add_emails([{'raw': binary(raw, 'text/html').as_bytes()}]) m = latest(parsed=True) assert m['meta']['preview'] == '' assert m['body'] == '<p><img><img><img style="color:red"><img></p>' msg = binary('', 'application/json') msg.add_header('Content-Disposition', 'attachment; filename="1/f/ /.json"') gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [ { 'filename': '1-f---.json', 'path': '', 'size': 0, 'url': '/raw/5/1-f---.json', } ] assert m['meta']['preview'] == '[1-f---.json]' assert m['body'] == '' msg = MIMEPart() msg.make_related() msg.attach(binary(' ', 'text/plain')) msg.attach(binary(' ', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' msg = MIMEPart() msg.make_alternative() msg.attach(binary(' ', 'text/plain')) msg.attach(binary(' ', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' msg = MIMEPart() msg.make_mixed() msg.attach(binary('plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'plain html' assert m['body'] == '<p>plain</p><hr><p>html</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_alternative() msg.attach(binary('plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html' assert m['body'] == '<p>html</p>' assert m['body_txt'] == 'plain' msg = MIMEPart() msg.make_alternative() msg.attach(binary('plain', 'text/plain')) htm = MIMEPart() htm.make_related() htm.attach(binary('<p>html</p>', 'text/html')) msg.attach(htm) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html' assert m['body'] == '<p>html</p>' assert m['body_txt'] == 'plain' msg1 = MIMEPart() msg1.make_mixed() msg1.attach(msg) msg1.attach(binary('<p>html2</p>', 'text/html')) gm_client.add_emails([{'raw': msg1.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html html2' assert m['body'] == '<p>html</p><hr><p>html2</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_mixed() msg.attach(binary('<br>plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '<br>plain html' assert m['body'] == '<p><br>plain</p><hr><p>html</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_mixed() msg.attach(binary('1', 'application/json')) msg.attach(binary('2', 'application/json')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [ { 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('1', '2') ] assert m['body'] == '' assert m['meta']['preview'] == '[unknown-1.json, unknown-2.json]' msg1 = MIMEPart() msg1.make_mixed() msg1.attach(binary('1')) msg1.attach(msg) gm_client.add_emails([{'raw': msg1.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [ { 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('2.1', '2.2') ] assert m['body'] == '<p>1</p>' assert m['meta']['preview'] == '1 [unknown-2.1.json, unknown-2.2.json]' msg2 = MIMEPart() msg2.make_mixed() msg2.attach(msg) msg2.attach(binary('0')) msg2.attach(msg1) gm_client.add_emails([{'raw': msg2.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [ { 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('1.1', '1.2', '3.2.1', '3.2.2') ] assert m['body'] == '<p>0<br><br>1</p>' # test some real emails with attachments m = load_email('msg-attachments-one-gmail.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [ { 'filename': '20.png', 'image': True, 'path': '2', 'size': 544, 'url': '/raw/16/2/20.png', } ] assert '<hr>' not in m['body'] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-two-gmail.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [ { 'filename': '08.png', 'image': True, 'path': '2', 'size': 553, 'url': '/raw/17/2/08.png', }, { 'filename': '09.png', 'image': True, 'path': '3', 'size': 520, 'url': '/raw/17/3/09.png', } ] assert '<hr>' not in m['body'] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-two-yandex.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [ { 'filename': '49.png', 'image': True, 'path': '2', 'size': 482, 'url': '/raw/18/2/49.png', }, { 'filename': '50.png', 'image': True, 'path': '3', 'size': 456, 'url': '/raw/18/3/50.png', } ] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-textfile.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [ { 'filename': 'Дополнение4.txt', 'path': '2', 'size': 11, 'url': '/raw/19/2/Дополнение4.txt', } ] assert m['body'] == '<p>тест</p>' m = load_email('msg-rfc822.txt', parsed=True) assert m['meta']['files'] == [ { 'filename': 'unknown-2.eml', 'path': '2', 'size': 463, 'url': '/raw/20/2/unknown-2.eml', } ] # test embeds m = load_email('msg-embeds-one-gmail.txt', parsed=True) assert m['meta']['files'] == [{ 'content-id': '<ii_jcrlk9sk0_16122eb711c529e8>', 'filename': '50.png', 'image': True, 'path': '2', 'size': 456, 'url': '/raw/21/2/50.png', }] src = 'src="/raw/%s/2/50.png"' % m['meta']['origin_uid'] assert src in m['body']
from email.message import EmailMessage, MIMEPart import smtplib from argparse import ArgumentParser from django.contrib.auth.hashers import make_password if __name__ == '__main__': parser = ArgumentParser() parser.add_argument('email', help="No help for you") parser.add_argument('html') parser.add_argument('password') args = parser.parse_args() receiver = args.email sender = "*****@*****.**" sender_password = "******" server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login(sender, sender_password) part = MIMEPart() message = EmailMessage() message.set_content(args.html, 'html') message['Subject'] = "Смена пароля" message["From"] = sender message["To"] = receiver server.send_message(message)
def test_parts(gm_client, latest, load_email): gm_client.add_emails([{'raw': binary('').as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' assert m['body_txt'] is None raw = '<?xml version="1.0" encoding="UTF-8"?>' gm_client.add_emails([{'raw': binary(raw, 'text/html').as_bytes()}]) m = latest(parsed=True) assert m['meta']['preview'] == '' assert m['body'] == '' gm_client.add_emails([{'raw': binary(' a b\n c d').as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == ' a b c d' assert m['body'] == '<p> a b<br> c d</p>' raw = ('<p>' '<img data-style="test" />' '<img data-src="test" />' '<img data-style="color:blue" style="color:red" />' '<img src="test" />' '</p>') gm_client.add_emails([{'raw': binary(raw, 'text/html').as_bytes()}]) m = latest(parsed=True) assert m['meta']['preview'] == '' assert m['body'] == '<p><img><img><img style="color:red"><img></p>' msg = binary('', 'application/json') msg.add_header('Content-Disposition', 'attachment; filename="1/f/ /.json"') gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'filename': '1-f---.json', 'path': '', 'size': 0, 'url': '/raw/5/1-f---.json', }] assert m['meta']['preview'] == '[1-f---.json]' assert m['body'] == '' msg = MIMEPart() msg.make_related() msg.attach(binary(' ', 'text/plain')) msg.attach(binary(' ', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' msg = MIMEPart() msg.make_alternative() msg.attach(binary(' ', 'text/plain')) msg.attach(binary(' ', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '' assert m['body'] == '' msg = MIMEPart() msg.make_mixed() msg.attach(binary('plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'plain html' assert m['body'] == '<p>plain</p><hr><p>html</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_alternative() msg.attach(binary('plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html' assert m['body'] == '<p>html</p>' assert m['body_txt'] == 'plain' msg = MIMEPart() msg.make_alternative() msg.attach(binary('plain', 'text/plain')) htm = MIMEPart() htm.make_related() htm.attach(binary('<p>html</p>', 'text/html')) msg.attach(htm) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html' assert m['body'] == '<p>html</p>' assert m['body_txt'] == 'plain' msg1 = MIMEPart() msg1.make_mixed() msg1.attach(msg) msg1.attach(binary('<p>html2</p>', 'text/html')) gm_client.add_emails([{'raw': msg1.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == 'html html2' assert m['body'] == '<p>html</p><hr><p>html2</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_mixed() msg.attach(binary('<br>plain', 'text/plain')) msg.attach(binary('<p>html</p>', 'text/html')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] assert m['meta']['preview'] == '<br>plain html' assert m['body'] == '<p><br>plain</p><hr><p>html</p>' assert m['body_txt'] is None msg = MIMEPart() msg.make_mixed() msg.attach(binary('1', 'application/json')) msg.attach(binary('2', 'application/json')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('1', '2')] assert m['body'] == '' assert m['meta']['preview'] == '[unknown-1.json, unknown-2.json]' msg1 = MIMEPart() msg1.make_mixed() msg1.attach(binary('1')) msg1.attach(msg) gm_client.add_emails([{'raw': msg1.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('2.1', '2.2')] assert m['body'] == '<p>1</p>' assert m['meta']['preview'] == '1 [unknown-2.1.json, unknown-2.2.json]' msg2 = MIMEPart() msg2.make_mixed() msg2.attach(msg) msg2.attach(binary('0')) msg2.attach(msg1) gm_client.add_emails([{'raw': msg2.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'filename': 'unknown-%s.json' % p, 'path': p, 'size': 1, 'url': '/raw/%s/%s/unknown-%s.json' % (m['uid'], p, p), } for p in ('1.1', '1.2', '3.2.1', '3.2.2')] assert m['body'] == '<p>0<br><br>1</p>' # test some real emails with attachments m = load_email('msg-attachments-one-gmail.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [{ 'filename': '20.png', 'image': True, 'path': '2', 'size': 544, 'url': '/raw/16/2/20.png', }] assert '<hr>' not in m['body'] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-two-gmail.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [{ 'filename': '08.png', 'image': True, 'path': '2', 'size': 553, 'url': '/raw/17/2/08.png', }, { 'filename': '09.png', 'image': True, 'path': '3', 'size': 520, 'url': '/raw/17/3/09.png', }] assert '<hr>' not in m['body'] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-two-yandex.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [{ 'filename': '49.png', 'image': True, 'path': '2', 'size': 482, 'url': '/raw/18/2/49.png', }, { 'filename': '50.png', 'image': True, 'path': '3', 'size': 456, 'url': '/raw/18/3/50.png', }] assert 'ответ на тело' in m['body'] m = load_email('msg-attachments-textfile.txt', 'koi8-r', parsed=True) assert m['meta']['files'] == [{ 'filename': 'Дополнение4.txt', 'path': '2', 'size': 11, 'url': '/raw/19/2/Дополнение4.txt', }] assert m['body'] == '<p>тест</p>' m = load_email('msg-rfc822.txt', parsed=True) assert m['meta']['files'] == [{ 'filename': 'unknown-2.eml', 'path': '2', 'size': 463, 'url': '/raw/20/2/unknown-2.eml', }] # test embeds m = load_email('msg-embeds-one-gmail.txt', parsed=True) assert m['meta']['files'] == [{ 'content-id': '<ii_jcrlk9sk0_16122eb711c529e8>', 'filename': '50.png', 'image': True, 'path': '2', 'size': 456, 'url': '/raw/21/2/50.png', }] src = 'src="/raw/%s/2/50.png"' % m['meta']['origin_uid'] assert src in m['body']
def new(request): if request.method == "GET": # test data data = { "subject": "testing from outlook", "sender": "*****@*****.**", } form = EmailForm(data) return render(request, "mails/new.html", context={"form": form}) elif request.method == "POST": # getting textual data from FORM data = request.POST # getting files data from FORM files = request.FILES.getlist("attachments") from_email = data["sender"] receipients = [e.strip() for e in data["receiver"].split("\n")] subject = data["subject"] content = data["content"] content_html_image_encoded = parse_images_to_base64(content) # creating msg object part by part msg = EmailMessage() msg["From"] = from_email msg["Subject"] = subject msg.make_mixed() # content html_part = MIMEPart() html_part.set_content(content_html_image_encoded, subtype="html") msg.attach(html_part) # attachment if len(files) > 0: for f in files: maintype, subtype = f.content_type.split("/") msg.add_attachment( f.read(), maintype=maintype, subtype=subtype, filename=f.name, disposition="attachment", ) with smtplib.SMTP("smtp.office365.com", 587) as server: server.ehlo() server.starttls() server.login(data['outlook_email'], data['outlook_password']) for to in receipients: msg['To'] = to server.send_message(msg) del msg['To'] # creating bulkmail and save to db data = { "author": request.user, "sender": from_email, "receiver": receipients, "subject": subject, "content": content, "date": timezone.now(), } this_bulk = BulkEmail(**data) this_bulk.save() messages.add_message(request, messages.SUCCESS, "Mail Sent!") return redirect("profile")
def test_parts(gm_client, latest, load_email): msg = binary('1') gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert not m['meta']['files'] msg = MIMEPart() msg.make_mixed() msg.attach(binary('1', 'application/json')) msg.attach(binary('2', 'application/json')) gm_client.add_emails([{'raw': msg.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{'path': p, 'size': 1} for p in ('1', '2')] msg1 = MIMEPart() msg1.make_mixed() msg1.attach(binary('1')) msg1.attach(msg) gm_client.add_emails([{'raw': msg1.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'path': p, 'size': 1 } for p in ('2.1', '2.2')] msg2 = MIMEPart() msg2.make_mixed() msg2.attach(msg) msg2.attach(binary('2')) msg2.attach(msg1) gm_client.add_emails([{'raw': msg2.as_bytes()}]) m = latest(parsed=True) assert m['meta']['files'] == [{ 'path': p, 'size': 1 } for p in ('1.1', '1.2', '3.2.1', '3.2.2')] # test some real emails with attachments m = load_email('msg-attachments-one-gmail.txt', parsed=True) assert m['meta']['files'] == [{ 'filename': '20.png', 'path': '2', 'size': 523 }] m = load_email('msg-attachments-two-gmail.txt', parsed=True) assert m['meta']['files'] == [{ 'filename': '08.png', 'path': '2', 'size': 532 }, { 'filename': '09.png', 'path': '3', 'size': 503 }] m = load_email('msg-attachments-two-yandex.txt', parsed=True) assert m['meta']['files'] == [{ 'filename': '49.png', 'path': '2', 'size': 472 }, { 'filename': '50.png', 'path': '3', 'size': 443 }] # test embeds m = load_email('msg-embeds-one-gmail.txt', parsed=True) assert m['meta']['files'] == [{ 'content-id': '<ii_jcrlk9sk0_16122eb711c529e8>', 'filename': '50.png', 'path': '2', 'size': 443 }] url = '/raw/%s/2' % m['meta']['origin_uid'] assert url in m['body'] m = load_email('msg-embeds-external.txt', parsed=True) assert m['meta']['files'] == [] assert 'data-src="/proxy?url=%2F%2Fwww.gravatar.com' in m['body'] assert 'data-src="/proxy?url=http%3A%2F%2Fwww.gravatar.com' in m['body'] assert 'data-src="/proxy?url=https%3A%2F%2Fwww.gravatar.com' in m['body']
def is_html(part: MIMEPart) -> bool: """Return True if this MIMEPart is HTML.""" return part.get_content_type() == "text/html"
def is_file(part: MIMEPart) -> bool: """Return True if this MIMEPart is attached as a file.""" disposition = part.get_content_disposition() return disposition == "inline" or disposition == "attachment"