7

Python2.7 output format not getting as expected if body of email read from a file. user_info.txt is a file generated by another job which contains all the details of users. The output format of user_info.txt is nice. Where as sending that file as an email, output format changes completely. does am I doing something wrong when reading from the file? Can some body help me on this please?

script:

#!/usr/bin/env python
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

msg = MIMEMultipart('alternative')
msg['Subject'] = "User Info"

"""Create the body of the message"""
open_file = open('/tmp/user_info.txt')
user_info = MIMEText(open_file.read().encode("utf-8"), 'plain', 'utf-8')
msg.attach(user_info)
open_file.close()

"""Send the message via gmail SMTP server."""
server = smtplib.SMTP('smtp-relay.gmail.com', 587)
server.sendmail("admin", "user1@test.com", msg.as_string())
server.quit()

sample user_info.txt

user_name  Department_no ID          detail1     detail2 


aaaa          4         13           25088       32.000000

bbbbbbb       5         17           33280       42.000000

ccccccccccc   3          9           16896       22.000000

dddddd        5         17           33280       42.000000

eeeeeeeee     5         14           27136       36.000000

Email output:

user_name Department_no ID detail1 detail2

aaaa 4 13 25088 32.000000

bbbbbbb 5 17 33280 42.000000

ccccccccccc 3 9 16896 22.000000

dddddd 5 17 33280 42.000000

eeeeeeeee 5 14 27136 36.000000

Please check the email screenshot:

email

user6136315
  • 695
  • 4
  • 13
  • 37
  • Is the problem in the extra empty lines, or something else? – 9000 Apr 27 '17 at 23:05
  • 1
    When you say the "output format changes completely", what does that mean exactly? What are you getting instead of what you expected? – Alex von Brandenfels Apr 27 '17 at 23:07
  • added my email screenshot in the description. Please check – user6136315 Apr 27 '17 at 23:18
  • 2
    The email is not displaying "correctly" because it's not using a fixed-width font. It seems to me that it contains exactly the same characters as user_info.txt. Paste the contents of your email back into your text editor and I think you'll see that once displayed in a fixed-width font, it's formatted as you expected. What you really want to do is to make sure the email that's sent displays in a fixed-width font. I do not know how to do that. – Alex von Brandenfels Apr 27 '17 at 23:49
  • @Sweater-Baron it's not having same fixed width as user_info.txt. copied mail into a text editor, the format is not same as text file. – user6136315 Apr 28 '17 at 00:20
  • Interesting. Can you paste the email text into your question instead of the screenshot? – Alex von Brandenfels Apr 28 '17 at 00:24
  • @Sweater-Baron Added email output. – user6136315 Apr 28 '17 at 00:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142865/discussion-between-user6136315-and-sweater-baron). – user6136315 Apr 28 '17 at 00:29
  • `user_info = MIMEText(open_file.read().encode("utf-8"), 'plain', 'utf-8')` all is okay ! what expected ? Need work with `#!/usr/bin/python -u` mean binary mode and never touch file encoding/decoding system ! `Mode` is important if you want protect file bytes. Maybe you open file `binary` mode but you lose byte index on output proccess ! – dsgdfg May 02 '17 at 07:03
  • What is the encoding of user_info.txt? Have you tried with your python program to open the file, copy it and see the result? Especially that by default python2 will assume the encoding used with files is the one from your system, see `sys.getfilesystemencoding()` and compare it to the actual encoding of user_info.txt – Adonis May 03 '17 at 11:32
  • @dsgdfg I've included `#!/usr/bin/python -u` in my script to do not encode/decode,But no luck still output format changed. – user6136315 May 03 '17 at 16:47
  • @asettouf the default encoding is `utf-8` in my OS(encoding of user_info.txt is `utf-8`). tried to copy the file content into a variable stdout looks good. where as sending that stdout of variable as an email output format changes completely. – user6136315 May 03 '17 at 16:52
  • `TXT` files not a rich document,`TAB` and `" " space` have no effect ! Maybe you calculate spaces but lose region if font types is changed ! You want push file with nice format (best layout and readable ) **but no way with `TXT` format**, try use `HTML+CSS` for perfect outputs.... – dsgdfg May 05 '17 at 08:48
  • Can you tell me how did you created a txt file? In your txt file, space between 2 columns is not the same. 2nd thing each system has its own algorithm. So either maintain tab between columns or coma delimiter file or use html. – Ujjaval Moradiya May 05 '17 at 13:56
  • @UjjavalMoradiya another python scripts writes the stdout to a text file. stdout looks good and this script reads the text file as expected. The issue comes when the mail delivered. – user6136315 May 05 '17 at 16:45
  • @user6136315 another python script also in the same environment right? Where as you are getting mail in some another environment or in some another system which you don't know. Try to make csv file and tell me the output you are getting. At the end csv file is formatted txt right? So I think you will not have any problem in creating csv file – Ujjaval Moradiya May 06 '17 at 06:32
  • Why is this question still open? If I copy your correct output to a variable-width font editor, it looks exactly like the faulty mail output. As many have suggested, this problem can be solved by including a html version of the message (with possibly a html table). – Sebastiaan May 06 '17 at 13:03

2 Answers2

4

When sending email in MIMEText(... 'plain') format you don't have control over exactly how it is displayed by the reciever's mail client. Some will use variable width fonts, collapse whitespace, wrap lines in odd places - generally make your pretty fixed width table ugly.

One option is to send an html message body with the plain text as fallback.

...
msg = MIMEMultipart('alternative')
...
with open('/tmp/user_info.txt') as f:
    raw_text = f.read()

msg.attach(MIMEText(raw_text, 'plain'))
msg.attach(MIMEText(convert_to_html(raw_text), 'html'))

That leaves the question of how to implement that convert_to_html() function. I can see two reasonable options:

  • Just wrap in the basic <html>/<body> tags and a <pre>.
  • Actually parse back your plain text table into cells and make an html table.

If you have the data from before creating the text file, you might find it easier to make the table straight from that.

Either way, basic mail clients should fall back to the plain text version and fancy ones that insist on messing with layout will get the html version that specifies you want your message in table form.

Community
  • 1
  • 1
gz.
  • 6,661
  • 1
  • 23
  • 34
3

Question ... output format changes completely. does am I doing something wrong when reading from the file

Tested with Python:3.4.2 and 2.7.9, your code and given user_info.txt format with no failure.
Could receive user_info.txt in the same format.
So, you are doing nothing wrong.


Try the following, without sending your eMail, to verify your used email.mime module work as expected. The output should be OK.

result = user_info.get_payload(decode=True).decode('utf-8','ignore')
print(result)

In general there is no guarantee that a receiver of a eMail uses the same font, size or the same environment.

If you want to be sure, data layout looks the same use a Portabel Document Format.

stovfl
  • 14,998
  • 7
  • 24
  • 51