Dotfiles/bin/.bin/emails/convertToHtmlMultipart
2020-05-03 17:31:12 +01:00

239 lines
8.3 KiB
Python
Executable file

#!/usr/bin/env python3
# Original Source: https://github.com/oblitum/dotfiles/blob/ArchLinux/.local/bin/MIMEmbellish
import re
import sys
import email
import shlex
import mimetypes
import subprocess
from copy import copy
from hashlib import md5
from email import charset
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.nonmultipart import MIMENonMultipart
from os.path import basename, splitext, expanduser
charset.add_charset('utf-8', charset.SHORTEST, '8bit')
def pandoc(from_format, to_format='markdown', plain='markdown', title=None):
markdown = ('markdown'
'-blank_before_blockquote')
if from_format == 'plain':
from_format = plain
if from_format == 'markdown':
from_format = markdown
if to_format == 'markdown':
to_format = markdown
command = 'pandoc -f {} -t {} --standalone --highlight-style=tango'
if to_format in ('html', 'html5'):
if title is not None:
command += ' --variable=pagetitle:{}'.format(shlex.quote(title))
command += ' --webtex --template={}'.format(
expanduser('~/.pandoc/templates/email.html'))
return command.format(from_format, to_format)
def gmailfy(payload):
return payload.replace('<blockquote>',
'<blockquote class="gmail_quote" style="'
'padding: 0 7px 0 7px;'
'border-left: 2px solid #cccccc;'
'font-style: italic;'
'margin: 0 0 7px 3px;'
'">')
def make_alternative(message, part):
alternative = convert(part, 'html',
pandoc(part.get_content_subtype(),
to_format='html',
title=message.get('Subject')))
alternative.set_payload(gmailfy(alternative.get_payload()))
return alternative
def make_replacement(message, part):
return convert(part, 'plain', pandoc(part.get_content_subtype()))
def convert(part, to_subtype, command):
payload = part.get_payload()
if isinstance(payload, str):
payload = payload.encode('utf-8')
else:
payload = part.get_payload(None, True)
if not isinstance(payload, bytes):
payload = payload.encode('utf-8')
process = subprocess.run(
shlex.split(command),
input=payload, stdout=subprocess.PIPE, check=True)
return MIMEText(process.stdout, to_subtype, 'utf-8')
def with_alternative(parent, part, from_signed,
make_alternative=make_alternative,
make_replacement=None):
try:
alternative = make_alternative(parent or part, from_signed or part)
replacement = (make_replacement(parent or part, part)
if from_signed is None and make_replacement is not None
else part)
except:
return parent or part
envelope = MIMEMultipart('alternative')
if parent is None:
for k, v in part.items():
if (k.lower() != 'mime-version'
and not k.lower().startswith('content-')):
envelope.add_header(k, v)
del part[k]
envelope.attach(replacement)
envelope.attach(alternative)
if parent is None:
return envelope
payload = parent.get_payload()
payload[payload.index(part)] = envelope
return parent
def tag_attachments(message):
if message.get_content_type() == 'multipart/mixed':
for part in message.get_payload():
if (part.get_content_maintype() in ['image']
and 'Content-ID' not in part):
filename = part.get_param('filename',
header='Content-Disposition')
if isinstance(filename, tuple):
filename = str(filename[2], filename[0] or 'us-ascii')
if filename:
filename = splitext(basename(filename))[0]
if filename:
part.add_header('Content-ID', '<{}>'.format(filename))
return message
def attachment_from_file_path(attachment_path):
try:
mime, encoding = mimetypes.guess_type(attachment_path, strict=False)
maintype, subtype = mime.split('/')
with open(attachment_path, 'rb') as payload:
attachment = MIMENonMultipart(maintype, subtype)
attachment.set_payload(payload.read())
encoders.encode_base64(attachment)
if encoding:
attachment.add_header('Content-Encoding', encoding)
return attachment
except:
return None
attachment_path_pattern = re.compile(r'\]\s*\(\s*file://(/[^)]*\S)\s*\)|'
r'\]\s*:\s*file://(/.*\S)\s*$',
re.MULTILINE)
def link_attachments(payload):
attached = []
attachments = []
def on_match(match):
if match.group(1):
attachment_path = match.