3

I made a simple program that automatically sends emails for me.

However when I send emails from riseup.net or protonmail I sometimes get failed to deliver because gmail requires "from" headers.

This is what the error looks like

This is the mail system at host mx1.riseup.net.

I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to postmaster.

If you do so, please include this problem report. You can delete your own text from the attached returned message.

The mail system

: host aspmx.l.google.com[74.125.142.27] said: 550-5.7.1 [198.252.153.129 11] Our system has detected that this message is 550-5.7.1 not RFC 5322 compliant: 550-5.7.1 'From' header is missing. 550-5.7.1 To reduce the amount of spam sent to Gmail, this message has been 550-5.7.1 blocked. Please visit 550-5.7.1 https://support.google.com/mail/?p=RfcMessageNonCompliant 550 5.7.1 and review RFC 5322 specifications for more information. 62si8602934pjo.111 - gsmtp (in reply to end of DATA command)

I looked up how to add a from header but I cannot get it to work for some reason.

This is my code

def send_mail():
    context = ssl.create_default_context()
    with smtplib.SMTP(smtp_server, 587) as server:
        server.starttls(context=context)
        server.login(susername, spassword)
        server.sendmail(semail, recipient, message)
        print("Email has been sent!")

edit: Riseup automatically adds this header when I send an email from within the browser but not when I use python to login to their SMTP server.

Nilanka Manoj
  • 3,527
  • 4
  • 17
  • 48
victorbrowser
  • 71
  • 1
  • 6
  • Can you show how you have tried to add the header? – dspencer Mar 14 '20 at 14:41
  • @dspencer I tried doing this server.sendmail(semail[header], recipient, message) and server.sendmail(semail, recipient, message[header]) as I saw it somewhere online. – victorbrowser Mar 14 '20 at 15:26
  • Please add your attempt, and preferably the source (where you found it online), to the question. It will make it easier for us to help you. – dspencer Mar 14 '20 at 15:30
  • I did above @dspencer here are the pages I've read. https://stackoverflow.com/questions/31132108/add-subject-header-to-server-sendmail-in-python https://pymotw.com/2/smtplib/ https://docs.python.org/3/library/email.examples.html – victorbrowser Mar 14 '20 at 15:39
  • Your code example is incomplete: where are `semail`, `recipient` and `message` defined? – dspencer Mar 14 '20 at 15:41
  • Ah I see, yes they are. – victorbrowser Mar 14 '20 at 16:37
  • semail = config['victorlean']['sender_email'] spassword = config['victorlean']['sender_password'] susername = config['victorlean']['sender_username'] uemail = "victorlean@riseup.net" @dspencer – victorbrowser Mar 14 '20 at 16:38

2 Answers2

2

I was facing the same issue. I was able to resolve it by explicitly adding a From: field within the message body. For example, the below message body will work:

message = """From: <your email address>
To: <receiver's email address>\n
Subject: <your subject>\n

Hi, this is a test mail! """

Got the idea from the link in your comment: Add Subject header to server.sendmail() in Python

Tim John
  • 192
  • 2
  • 17
0

I can't give an definite answer, but perhaps a few guidelines.

You wrote that you don't modify the return path when forwarding. However, it would be more relevant to know if you leave the envelope intact. The following assumes that you at least don't modify the envelope sender.

First, let's look at SPF:

Without special measures, it is understandable that Google treats the messages as spam. SPF works like that (oversimplified):

When a message arrives, the receiving server extracts the pretended sender domain from the envelope address (pretended because the envelope can easily be faked), then asks the DNS server of that domain whether the current communication partner's IP address is authorized to send email in behalf of that domain. If it isn't, it is likely that the message is treated as spam.

This is what happens in your case (without SRS). The original envelope sender domain's DNS server probably does not have your EXIM SMTP server in the list of hosts which may send email on behalf of that domain. You can't do anything about that, unless you control that DNS server.

SRS theoretically can mitigate the problem, but it has its own issues. The main problem is that every SMTP server which is involved in transporting the respective messages must handle the respective headers correctly.

You have described that everything was working with SRS turned on, but it suddenly stopped a few days ago. My personal guess is that since an additional SMTP server is involved in transporting your forwarded messages, and that this server doesn't treat SRS correctly. Something bad could even happen before your EXIM server receives that messages.

DKIM shouldn't have the problems denoted above as long as you leave the envelope sender address intact.

Now, my first advice would be to send messages to your EXIM server's special, forwarded address from as many different sender domains as possible. It would be very interesting to know whether all of the forwarded messages get rejected, or only a few of them. The result could give a hint about where the problem is. You probably would want to enable SRS for this test.

You should also check which authorization the messages already have which arrive at your EXIM server to your special address. I have no clue about EXIM, so I can't tell you whether it supports checking SPF or DKIM headers. But what I can say for sure is that it wouldn't be the first time that somebody at the original sender's site misconfigures DKIM or SPF; in the latter case, SRS won't help of course.

At least in case of SPF, you can check the situation yourself without re-configuring EXIM.

First, store one of the problematic messages (in addition to or instead of forwarding it). In the headers of that message, you can identify the IP address of the SMTP server which has delivered the message to your EXIM server. For clarification: If the message ran through multiple SMTP servers, there would be multiple Received: header lines; you need the one which designates the last SMTP server which directly connected to your EXIM server when delivering the message. Write down the IP address of that server. Next, identify the envelope sender domain. That may be a bit hard because SMTP servers usually do not add the envelope data to the headers (again, no clue about EXIM). That is, email client software can't show that data. But it should be in the logs. You really need to get the sender's domain from the envelope data, not the normal message headers. Next, use software like host or dig (or eventually some online service) to examine the DNS SPF entries of the envelope sender's domain. Check if the IP address from step 1 is in the list of allowed servers. The next thing you could test is to turn off SPF and DKIM at all and to filter out the respective headers before forwarding the message. After all, it may be better to not authenticate a message at all than to authenticate it in a way that makes the receiver think that it has been tampered with. Of course, this is only for testing to gain further insight.

Finally, violating the precondition from the second paragraph, you could purposely change the envelope sender (replacing the envelope sender by your own email address with a domain part whose DNS entries are under your control) and turn off SRS. That way, when forwarding the message, the receiving server would consult your DNS server for the SPF checks. If you have set it up correctly, no more problems with SPF should arise. In this case, you should filter out headers which designate the original envelope sender (as stated above, it is usually not in the headers anyway, but I only know sendmail, so your mileage may vary).

However, when changing the envelope sender, you'll have problems with DKIM, so you should remove the DKIM headers in this case.

Happy testing, and good luck.

P.S. I'll eventually update the answer and give further hints (if I am able to) when you give test results or explain more precisely whether or not you change the envelope.

  • While this is informative, it doesn't answer the question, which is effectively "How can I add a from header using Python's smtplib package?" – snakecharmerb Aug 13 '22 at 13:58