2

I am new to python. Below is the code we are using for sending mail.

import smtplib
import shutil
import os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders

To="maniram.220@gmailcom"
Subject="mail through code"
Text="Hai!"
mail_sender="pull@gmail.com"
mail_passwd="ZSDCXFF"

server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo
server.login(mail_sender,mail_passwd)
BODY='\r\n' .join(['To: %s' % To,'From: %s' % mail_sender,'Subject: %s' % Subject,'',Text])
try:
    server.sendmail(mail_sender,[To],BODY)
    print("email sent")
except:
    print("error sending email")
    server.quit()

I need to zip the files in folder(path given by user) and then mail it as an attachment.
How can I attain this?

Abey
  • 1,408
  • 11
  • 26
mani ram
  • 21
  • 4

1 Answers1

0

The following shows that it may not be necessary to zip up an entire directory to attach it to an email. Instead, just adjust the FILE_PATHS variable as needed to take all the files into account. Alternately, you are free to use create_attachment which automatically identifies directories, zips them up, and creates a well-named attachment for inclusion in the email.

#! /usr/bin/env python3
import collections
import contextlib
import email.encoders
import email.mime.application
import email.mime.audio
import email.mime.base
import email.mime.image
# import email.mime.message
import email.mime.multipart
import email.mime.text
import email.utils
import getpass
import mimetypes
import pathlib
import smtplib
import string
import tempfile
import uuid
import zipfile

FROM = 'John Doe', 'john.doe@gmail.com'
SUBJECT = 'Email Demonstration'
TO = [
    ('Jane Doe', 'jane.doe@gmail.com'),
    ('Mary Doe', 'mary.doe@gmail.com')
]
FILE_PATHS = [
    pathlib.Path(r'C:\path\to\my\file'),
    pathlib.Path(r'C:\path\to\another\file'),
    pathlib.Path(r'C:\path to\yet\another\file'),
    pathlib.Path(r'C:\why\are\there\so\many\paths')
]
PLAIN_MESSAGE = '''\
Hello, Jane and Mary!
How are you doing?
Hope you like the email.'''
HTML_TEMPLATE = r'''<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="${content_type}">
    <title>${title}</title>
    <style type="text/css" media="all">
        .key {
            color: #0066AA;
            font-family: sans-serif;
            font-size: 14px;
            font-weight: bold;
        }
        .value {
            color: #000000;
            font-family: monospace;
            font-size: 12px;
            font-weight: normal;
        }
    </style>
</head>
<body>
<div class="value">
    <span class="key">${header}</span>
${message}
</div>
<div class="value">
    <span class="key">File Manifest</span>
${manifest}
</div>
</body>
</html>'''
HTML_MESSAGE = [
    'When will the event start, and how much time do ushers need to show up '
    'before the event?',
    'Who will be admitted to the event, will they require tickets, and what '
    'is to be done if we run out of room?',
    'Where will the event be taking place, and will ushers need to enter '
    'through a different way than everyone else?',
    'How do you want your ushers to act, and will you have a rehearsal or '
    'practice session explaining your expectations?',
    'What clothing do you want ushers to where; and do you want the standard '
    'black suit, white shirt, and red tie ushers usually where around here?'
]


def main():
    message = create_multipart()
    for path in FILE_PATHS:
        mime, handle = create_attachment(path)
        message.attach(mime)
    message.attach(email.mime.text.MIMEText(PLAIN_MESSAGE, 'plain'))
    attach_html_text(message)
    with smtplib.SMTP('smtp.gmail.com', 587) as server:
        server.starttls()
        server.login(input('Username: '), getpass.getpass())
        server.send_message(message)


def create_multipart():
    message = email.mime.multipart.MIMEMultipart('alternative')
    message['Message-ID'] = make_message_id()
    message['From'] = email.utils.formataddr(FROM)
    message['Date'] = email.utils.formatdate(localtime=True)
    message['Subject'] = SUBJECT
    message['To'] = email.utils.COMMASPACE.join(map(
        email.utils.formataddr, TO
    ))
    return message


def make_message_id():
    return email.utils.make_msgid(str(uuid.uuid4()))


@contextlib.contextmanager
def create_temp_zip_file(directory):
    paths_to_zip = collections.deque([directory])
    with tempfile.TemporaryDirectory() as root:
        handle = pathlib.Path(root) / f'{directory.name}.zip'
        with zipfile.ZipFile(handle, 'x') as file:
            while paths_to_zip:
                path = paths_to_zip.popleft()
                if path.is_dir():
                    paths_to_zip.extend(path.iterdir())
                elif path.is_file():
                    file.write(path, path.relative_to(directory))
        yield handle


def create_attachment(path):
    if path.is_dir():
        with create_temp_zip_file(path) as handle:
            return create_attachment(handle)
    kind, encoding = mimetypes.guess_type(str(path))
    if kind is None:
        kind = 'application/octet-stream'
    main_type, sub_type = kind.split('/')
    if main_type == 'application':
        with path.open('rb') as file:
            mime = email.mime.application.MIMEApplication(
                file.read(),
                sub_type
            )
    elif main_type == 'audio':
        with path.open('rb') as file:
            audio_data = file.read()
        try:
            mime = email.mime.audio.MIMEAudio(audio_data)
        except TypeError:
            mime = email.mime.audio.MIMEAudio(audio_data, sub_type)
    elif main_type == 'image':
        with path.open('rb') as file:
            image_data = file.read()
        try:
            mime = email.mime.image.MIMEImage(image_data)
        except TypeError:
            mime = email.mime.image.MIMEImage(image_data, sub_type)
    # elif main_type == 'message':
    #     attachment = email.mime.message.MIMEMessage()
    elif main_type == 'text':
        with path.open('rt') as file:
            mime = email.mime.text.MIMEText(file.read(), sub_type)
    else:
        mime = email.mime.base.MIMEBase(main_type, sub_type)
        with path.open('rb') as file:
            mime.set_payload(file.read())
        email.encoders.encode_base64(mime)
    mime.add_header('Content-Disposition', 'attachment', filename=path.name)
    content_id = make_message_id()
    mime.add_header('Content-ID', content_id)
    handle = f'"cid:{content_id.strip("<>")}"'
    return mime, handle


def attach_html_text(message):
    mapping = dict(
        content_type='',
        title=message['Subject'],
        header=message['Subject'],
        message=make_html_list(HTML_MESSAGE, 'o', 1),
        manifest=make_html_list(FILE_PATHS, 'u', 1)
    )
    template = string.Template(HTML_TEMPLATE)
    mime = email.mime.text.MIMEText(template.substitute(mapping), 'html')
    mapping['content_type'] = mime['Content-Type'].replace('"', '')
    mime = email.mime.text.MIMEText(template.substitute(mapping), 'html')
    message.attach(mime)


def make_html_list(iterable, kind, indent=0, space=' ' * 4):
    prefix = space * indent
    elements = [f'{prefix}<{kind}l>']
    elements.extend(f'{prefix}{space}<li>{item}</li>' for item in iterable)
    elements.append(f'{prefix}</{kind}l>')
    return '\n'.join(elements)


if __name__ == '__main__':
    main()
Noctis Skytower
  • 21,433
  • 16
  • 79
  • 117