email modules and attachments that aren't there

Discussion in 'Python' started by Russell Bungay, Jan 9, 2006.

  1. Hello all,

    I have written a short function, based on a recipe in the Python
    Cookbook, that sends an e-mail. The function takes arguments that
    define who the e-mail is to, from, the subject, the body and an optional
    list of attachments.

    The function works also perfectly, bar one slight problem. If you
    attempt to send an e-mail with just a body and no attachments, the
    receiving client still thinks that there is an attachment (so far tested
    in Mozilla Thunderbird and the Yahoo! webmail client). Although this
    clearly isn't a major problem, it is irritating and I am hoping to use
    my code at work. Obviously I can't be sending out badly formed e-mails
    to my clients.

    I can't for the life of me work out why. I have compared my code to
    every example that I can find in the Python documentation, on the
    archives of this newsgroup and of the Python Tutor list, and one or two
    random searches but can't see what is happening. Any advice or
    suggestions would be welcome.

    Thank you for your help,

    Russell Bungay
    --
    The Duck Quacks:
    http://www-users.york.ac.uk/~rb502/ - Homepage
    http://www-users.york.ac.uk/~rb502/blog/quack.shtml - Blog
    http://www.flickr.com/photos/lsnduck/ - Photos

    Code:

    def sendEmail(msg_to, msg_from, msg_subject, message, attachments=[]):

    main_msg = email.Message.Message()
    main_msg['To'] = ', '.join(msg_to)
    main_msg['From'] = msg_from
    main_msg['Subject'] = msg_subject
    main_msg['Date'] = email.Utils.formatdate(localtime=1)
    main_msg['Message-ID'] = email.Utils.make_msgid()
    main_msg['Mime-version'] = '1.0'
    main_msg['Content-type'] = 'Multipart/mixed'
    main_msg.preamble = 'Mime message\n'
    main_msg.epilogue = ''

    body_encoded = quopri.encodestring(message, 1)
    body_msg = email.Message.Message()
    body_msg.add_header('Content-type', 'text/plain')
    body_msg.add_header('Content-transfer-encoding', 'quoted-printable')
    body_msg.set_payload(body_encoded)
    main_msg.attach(body_msg)

    for attachment in attachments:

    content_type, ignored = mimetypes.guess_type(attachment)
    if content_type == None:
    content_type = 'application/octet-stream'
    contents_encoded = cStingIO.StringIO()
    attach_file = open(attachment, 'rb')
    main_type = content_type[:content_type.find('/')]
    if main_type == 'text':
    cte = 'quoted-printable'
    quopri.encode(attach_file, contents_encoded, 1)
    else:
    cte = 'base64'
    base64.encode(attach_file, contents_encoded)
    attach_file.close()

    sub_msg = email.Message.Message()
    sub_msg.add_header('Content-type', content_type, name=attachment)
    sub_msg.add_header('Content-transfer-encoding', cte)
    sub_msg.set_payload(contents_encoded.getvalue())
    main_msg.attach(sub_msg)

    smtp = smtplib.SMTP(server)
    smtpfail = smtp.sendmail(msg_from, ', '.join(msg_to),
    main_msg.as_string())
    smtp.quit()
    Russell Bungay, Jan 9, 2006
    #1
    1. Advertising

  2. Russell Bungay wrote:

    > Hello all,
    >
    > I have written a short function, based on a recipe in the Python
    > Cookbook, that sends an e-mail. The function takes arguments that
    > define who the e-mail is to, from, the subject, the body and an optional
    > list of attachments.
    >
    > The function works also perfectly, bar one slight problem. If you
    > attempt to send an e-mail with just a body and no attachments, the
    > receiving client still thinks that there is an attachment (so far tested
    > in Mozilla Thunderbird and the Yahoo! webmail client).


    <snip>

    > Code:
    >
    > def sendEmail(msg_to, msg_from, msg_subject, message, attachments=[]):
    >
    > main_msg = email.Message.Message()
    > main_msg['To'] = ', '.join(msg_to)
    > main_msg['From'] = msg_from
    > main_msg['Subject'] = msg_subject
    > main_msg['Date'] = email.Utils.formatdate(localtime=1)
    > main_msg['Message-ID'] = email.Utils.make_msgid()
    > main_msg['Mime-version'] = '1.0'
    > main_msg['Content-type'] = 'Multipart/mixed'
    > main_msg.preamble = 'Mime message\n'
    > main_msg.epilogue = ''


    Would it be the 'Content-Type' header? I've no expertise in this, but
    doesn't 'multipart' mean 'has attachments'?

    Gerard
    Gerard Flanagan, Jan 9, 2006
    #2
    1. Advertising

  3. Russell Bungay, Jan 10, 2006
    #3
  4. Hello,

    >>> main_msg['Content-type'] = 'Multipart/mixed'

    >> Would it be the 'Content-Type' header? I've no expertise in this, but
    >> doesn't 'multipart' mean 'has attachments'?

    > Brilliant, thank you. A swift test on the number of attachments and
    > changing the header suitably does the job.


    That isn't quite all there is to it, the e-mail construction needs a
    slight change as well. Roughly working code below.

    Ta,

    Russell

    Code:

    def sendEmail(msg_to, msg_from, msg_subject, message, attachments=[]):

    main_msg = email.Message.Message()
    main_msg['To'] = ', '.join(msg_to)
    main_msg['From'] = msg_from
    main_msg['Subject'] = msg_subject
    main_msg['Date'] = email.Utils.formatdate(localtime=1)
    main_msg['Message-ID'] = email.Utils.make_msgid()
    main_msg['Mime-version'] = '1.0'
    main_msg.preamble = 'Mime message\n'
    main_msg.epilogue = ''

    body_encoded = quopri.encodestring(message, 1)

    if len(attachments) <> 0:
    main_msg['Content-type'] = 'Multipart/mixed'
    body_msg = email.Message.Message()
    body_msg.add_header('Content-type', 'text/plain')
    body_msg.add_header('Content-transfer-encoding',
    'quoted-printable')
    body_msg.set_payload(body_encoded)
    main_msg.attach(body_msg)
    for attachment in attachments:
    content_type, ignored = mimetypes.guess_type(attachment)
    if content_type == None:
    content_type = 'application/octet-stream'
    contents_encoded = cStringIO.StringIO()
    attach_file = open(attachment, 'rb')
    main_type = content_type[:content_type.find('/')]
    if main_type == 'text':
    cte = 'quoted-printable'
    quopri.encode(attach_file, contents_encoded, 1)
    else:
    cte = 'base64'
    base64.encode(attach_file, contents_encoded)
    attach_file.close()

    sub_msg = email.Message.Message()
    sub_msg.add_header('Content-type', content_type, name=attachment)
    sub_msg.add_header('Content-transfer-encoding', cte)
    sub_msg.set_payload(contents_encoded.getvalue())
    main_msg.attach(sub_msg)

    else:
    main_msg['Content-type'] = 'text/plain'
    main_msg['Content-transfer-encoding'] = 'quoted-printable'
    main_msg.set_payload(body_encoded)

    smtp = smtplib.SMTP('server')
    smtpfail = smtp.sendmail(msg_from, ', '.join(msg_to),
    main_msg.as_string())
    smtp.quit()
    Russell Bungay, Jan 10, 2006
    #4
  5. Russell Bungay wrote:

    > for attachment in attachments:
    > <snip contents of for loop>


    > sub_msg = email.Message.Message()
    > sub_msg.add_header('Content-type', content_type, name=attachment)
    > sub_msg.add_header('Content-transfer-encoding', cte)
    > sub_msg.set_payload(contents_encoded.getvalue())
    > main_msg.attach(sub_msg)


    These lines should of course be within the for, not outside it. Apologies.

    Russell
    Russell Bungay, Jan 10, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    1,105
    Mike Meyer
    Jun 22, 2005
  2. codewarrior
    Replies:
    0
    Views:
    526
    codewarrior
    May 4, 2009
  3. Lango
    Replies:
    4
    Views:
    569
    aleksa
    Oct 19, 2009
  4. Peter Green
    Replies:
    0
    Views:
    636
    Peter Green
    Nov 5, 2009
  5. Don McLaughlin

    modules to detach attachments and form replies?

    Don McLaughlin, Oct 13, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    123
    Don McLaughlin
    Oct 16, 2005
Loading...

Share This Page