email: Content-Disposition and linebreaks with long filenames

  • Thread starter =?ISO-8859-15?Q?Martin_K=F6rner?=
  • Start date
?

=?ISO-8859-15?Q?Martin_K=F6rner?=

Hi NG,

I am using email module for creating mails with attachment (and then
sending via smtplib).

If the name of the attachment file is longer than about 60 characters
the filename is wrapped in the Content-Disposition header:

Content-Disposition: attachment;
filename="This is a sample file with a very long filename
0123456789.zip"


This leads to a wrong attachment filename in email clients - the space
after "filename" is not shown or the client displays a special character
(the linbreak or tab before 0123456789.zip).

If I use a standard email client and generate a mail with the same
attachment, it creates the following header:

Content-Disposition: attachment;
filename="This is a sample file with a very long filename 0123456789.zip"

(no line break)

Here is my code:


msg = MIMEMultipart()
msg['Subject'] = 'Test'
msg['From'] = 'my@address'
msg['To'] = 'my@address'
msg.epilogue = ''

# Add body
part_body = MIMEText('blabla')
msg.attach(part_body)

# Add attachment
file = 'This is a sample file with a very long filename 0123456789.zip'
fp = open(file, 'rb')
part_att = MIMEBase('application','zip')
part_att.set_payload(fp.read())
fp.close()
part_att.add_header('Content-Disposition', 'attachment', filename=file)

# Encode the payload using Base64
email.Encoders.encode_base64(part_att)

msg.attach(part_att)


Is it possible to prevent the linebreak?

Thank you
Martin
 
?

=?ISO-8859-1?Q?Andr=E9?= Malo

* Martin Körner said:
I am using email module for creating mails with attachment (and then
sending via smtplib).

If the name of the attachment file is longer than about 60 characters
the filename is wrapped in the Content-Disposition header:

Content-Disposition: attachment;
filename="This is a sample file with a very long filename
0123456789.zip"


This leads to a wrong attachment filename in email clients - the space
after "filename" is not shown or the client displays a special character
(the linbreak or tab before 0123456789.zip).

Yeah, this is badly applied header folding. You can circumvent it by
encoding the filename parameter according to
<http://ftp.rfc-editor.org/in-notes/rfc2184.txt>

Note that parameter continuation ala filename*1="..."; filename*2="...." is not
really supported by MUAs, but support for filename*="..." seems to be a /bit/ better.

nd
 
D

David Bolen

Martin Körner said:
I am using email module for creating mails with attachment (and then
sending via smtplib).

If the name of the attachment file is longer than about 60 characters
the filename is wrapped in the Content-Disposition header:

Content-Disposition: attachment;
filename="This is a sample file with a very long filename
0123456789.zip"


This leads to a wrong attachment filename in email clients - the space
after "filename" is not shown or the client displays a special
character (the linbreak or tab before 0123456789.zip).

Yes, it would appear that the default Generator used by the Message
object to create a textual version of a message explicitly uses tab
(\t) as a continuation character rather than space - probably because
it looks a little nicer when printed. Interestingly enough, the
default Header continuation character is just a plain space which
would work fine here.

I should point out that I believe this header format could be
considered correct, although I find RFC2822 a bit ambiguous on this
point. It talks about runs of FWS (folding white space) in an
unfolding operation as being considered a single space (section
3.2.3). However, I suppose someone might argue if "runs" includes a
single character. I think it should, but obviously some e-mail
clients disagree :)

(...)
Is it possible to prevent the linebreak?

Should be - two approaches I can think of (msg below is the email.Message):

1) Create your own Header object for the specific header line rather than
just storing it as a string via add_header. For that specific header you
can then override the default maximum line length. Something like:

from email.Header import Header

cd_header = Header('Content-Disposition: attachment; filename="....."',
maxlinelen=998)
msg['Content-Disposition'] = cd_header

Note that because Header defaults to a space continuation character,
you could also leave maxlinelen alone and let it break the line, but
since it would break with a single space it would work right in clients.

2) Use your own Generator object to generate the textual version of the
message (which is when the wrapping is occurring), and during the
flattening process, disable (or set a longer value for) header wrapping.
Something like:

Assuming "fp" is an output File-like object:

from email.Generator import Generator

g = Generator(fp)
g.flatten(msg, maxheaderlen=998) (or maxheaderlen=0 to disable wrapping)


-- David
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top