Get original e-mail sender server in Python - python

With many e-mail services, you can get tricked into believing an e-mail has been sent from a different address.
Using smtplib in Python, you can easily do the trick by manipulating the From argument.
gmail is not prone to that as they print the via argument which shows the original server.
However, what I cannot find anywhere is how do you retrieve the original (not manipulated) server name in Python, the same as gmail does with their via functionality?
I've tried the imaplib and email libraries, but there I can only access the already manipulated sender.
Any ideas? Is that solely linked to the configuration of a particular provider (e.g. Google, Outlook, hotmail, etc.), or can something be done regardless of that?
Here is part of the code I'm currently using (no success):
import imaplib
import email
obj = imaplib.IMAP4('imap', portn)
obj.login('username', 'password')
obj.select('INBOX')
uidl_list = [68720]
resp, data = obj.uid('FETCH', ','.join(map(str, uidl_list)) , '(BODY.PEEK[HEADER.FIELDS (From Subject)] RFC822.SIZE)')

Never heard about the via field. It is related to this particular provider.
You may check the Received headers of the mail to know what SMTP servers the message went through. Assuming those are not fake and were not modified along the way (i.e. assuming you trust the servers), they should point you to the SMTP server the user connected to to send the message.
Example:
Received: from mail-ot1-x333.google.com (mail-ot1-x333.google.com [IPv6:2617:f8c0:4864:20::331])
by smtp.domain.tld (Postfix) with ESMTPS id 6C488D0F8
for <user#domain.tld>; Mon, 19 Nov 2018 21:13:54 +0100 (CET)
Received: by mail-ot1-x333.google.com with SMTP id w25so38121669otm.11
for <user#domain.tld>; Mon, 19 Nov 2018 12:13:54 -0800 (PST)
A user connected to mail-ot1-x333.google.com, posted a message for user#domain.tld. The SMTP server added the Received header that appears at the bottom. Then, it sent the message to domain.tld, and Postfix server at domain.tld added the header that appears on top.
From RFC 5321, the Received headers are always added on top.
An Internet mail program MUST NOT change or delete a Received: line
that was previously added to the message header section. SMTP
servers MUST prepend Received lines to messages; they MUST NOT change
the order of existing lines or insert Received lines in any other
location.
The last one should always be the one indicating the SMTP server the user connected to.
Note that there are good reasons to have a From domain that does not match the SMTP server used for sending the message.:
ISP forces users to use their own SMTP server
Using several email accounts with a mail client that only offers a songle SMTP configuration

Related

DKIM fails when sending mails with smtplib

I'm trying to send emails with smtplib and they seem to be delivering fine. The only problem is that DKIM fails and the mails usually go straight to the spam folder.
DKIM is enabled on my shared hosting (host is a2hosting, if that helps) and the process works fine when sending individual emails with Thunderbird, and DKIM passes, suggesting that the problem lies on my end.
I even tried using dkimpy to explicitly sign the emails using the private key but I still get dkim=fail under ARC-Authentication-Results.
Some posts and answers I referred to suggested "logging in" as the solution but I am already logging in using SMTP.login() and as I mentioned earlier, the emails are being sent.
An answer I referred to mentioned that it is the server's job to sign the email and it's worth mentioning that the raw email output includes the DKIM signature, even without explicitly signing it with dkimpy, indicating that the server is signing as expected.
But the problem remains that DKIM fails affecting the email deliverability, and the raw output does not provide any details as to why DKIM failed for the domain.
I use the following code snippet to send an email
msg = MIMEMultipart()
msg['From'] = 'myemail#mydomain.tld'
msg['To'] = 'someemail#gmail.com'
msg['Subject'] = "Subject"
msg.attach(MIMEText("SomeText", "plain"))
s = smtplib.SMTP_SSL("mydomain.tld:465")
s.login("myemail#mydomain.tld", "mypassword")
s.sendmail("myemail#mydomain.tld", 'someemail#gmail.com',msg.as_string())
I tried signing the message as follows
headers = ["To", "From", "Subject"]
with open("cert.pem") as fh:
dkim_private = fh.read()
sig = dkim.sign(
message=msg.as_string().encode("ascii"),
selector=str(dkim_selector).encode("ascii"),
domain="robogyan.tech".encode("ascii"),
privkey=dkim_private.encode("ascii"),
include_headers=headers,)
msg["DKIM-Signature"] = sig.decode("ascii").lstrip("DKIM-Signature: ")
The raw output did reflect the signature with the above code but DKIM still failed.
There seems to be no problem with the authentication whatsoever since the server replies with "Authentication succeeded"
Edit:
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
d=mydomain.tld; s=default; h=Subject:To:From:MIME-Version:Content-Type:
Sender:Reply-To:Date:Message-ID:Cc:Content-Transfer-Encoding:Content-ID:
Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc
:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:
List-Subscribe:List-Post:List-Owner:List-Archive;
bh=giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=; b=DR08Q+CjgOLqo8WkLJs/XROfTw
Z7+ph+qnzi5p49cT3+UwQolcL1CKIVPk7XRkL8WZ3FFa9hZuc6TumquRSiYd5uR0AC5Z3lopEfnQe
fdbOOTRnks2ZzoOnQusy/gmydUttypu8wTthFhy7vTWXMFcdI29X/HkrokCtiGKCoD2u2kWBtn2sm
3/aP83lBbMpcWsNbvo3HTsL71o8QPd6bVKpqRGyAy89cAwMLwP4dnJ9WcCxxNzowlJNPQja3o5W16
t3rG/KizcRehjaDUXhPPRF/4RdYUSIi/SGNwmIPwvkZNc17k3wQpszKeG6/Ujgax/i7Li7V7dLJBT
Fu/x6xDA==;
Signed-by: myemail#mydomain.tld
Expected-Body-Hash: giCDGo/0duFr1Ex65l7Ixc3N45EAULK+gw5cHV8pO0k=
Here's the DKIM of the failing email if that helps. The expected body hash and the received body hash match too. I am not sure what the problem is then.
After a lot of research and brute force approaches, I finally found the solution to my problem.
I needed to include the Message-ID and the date in the headers as well.
Adding the following lines to the code helped me pass the verification.
msg['Date'] = email.utils.formatdate()
msg['Message-ID'] = email.utils.make_msgid(domain='mydomain.tld')
Important note: you need to add your smtp client's machine IP address to InternalHosts list, because OpenDKIM will check client's permission with these rules.
The you need to add this line to your /etc/opendkim.conf:
InternalHosts file:/etc/opendkim/TrustedHosts # or any location you want
Content of /etc/opendkim/TrustedHosts could look like:
127.0.0.1
::1
localhost
<server_ip>
hostname.example1.com
example1.com
hostname.example2.com
example2.com
...
It's just for example. You need to put here your python smtplib-client machine's address (ip/host).
Then just restart your opendkim:
$ sudo service opendkim restart

Sending email using python script from an Azure server

Using a python script, I am trying to send an email.
The mail part of the script looks like -
import smtplib
sender = 'abc.xyz#company.com'
receiver = 'abc.xyz#company.com'
message = """From: From Person <abc.xyz#company.com>
To: To Person <abc.xyz#company.com>
Subject: Inbound Folder Check - Alert
Unchanged even after an hour, please check
"""
smtpObj = smtplib.SMTP('smtp.office365.com',587)
smtpObj.starttls()
smtpObj.login('def#company.onmicrosoft.com','Password')
smtpObj.sendmail(sender, receiver, message)
The error that I am getting is -
raise SMTPDataError(code, resp) smtplib.SMTPDataError: (554, b'5.2.0
STOREDRV.Submission.Exception:SendAsDeniedE
xception.MapiExceptionSendAsDenied; Failed to process message due to a
permanent exception with message Cannot submit message. ...,
20.52176:140FCC8414001010640 10000, 20.50032:140FCC848417101069010000, 0.35180:0A006586, 255.23226:6E010000,
255.27962:0A000000, 255.27962:0E000000, 255.31418:0A00EB87, 16.55847:69000000, 1
7.43559:0000000090010000000000000D00000000000000, 20.52176:140FCC84140010100A00F 736, 20.50032:140FCC84841710100A00F836, 0.35180:8C010000, 255.23226:40000730, 25
5.27962:32000000, 255.17082:DC040000, 0.27745:9A010000, 4.21921:DC040000, 255.27 962:FA000000, 255.1494:0A00070E, 0.37692:01000100, 0.44092:01000100, 0.41232:010 00100, 0.60208:01000100, 0.37136:01000100, 0.34608:01000100, 0.55056:01000100, 0 .42768:01000100, 0.56112:05000780, 0.52807:00000000, 4.33016:DC040000, 7.40748:0 10000000000010C00000000, 7.57132:000000000000000005000780, 1.63016:32000000, 4.3 9640:DC040000, 8.45434:EC5537826FAD8844ABBA433565F1D57205000780, 5.10786:0000000 031352E32302E313232382E3032303A564931505230314D42323939303A38616433323065392D646
338612D343530642D386265322D62646464616261333932613900602005000780,
255.1750:4B01 0000, 255.31418:0A004C82, 0.22753:50010000, 255.21817:DC040000, 4.60547:DC040000 , 0.21966:B4100000, 4.30158:DC040000 [Hostname=abc]')
Only help I got on the internet was from the page - https://support.microsoft.com/en-us/help/3132755/554-5-2-0-storedrv-deliver-exception-objectnotfoundexception-mapiexcep
And it seems to say clutter is enabled but the folder is not present in the mailbox and suggests to turn off the clutter option which didn’t help.
PS - This works from my local machine within my company network but it is something to do with running it from Azure server.
First of all, please follow the offical document How to set up a multifunction device or application to send email using Office 365 to make sure whether set up correctly.
Secondly, if you were using Azure VM to send mail via SMTP, you can refer to this document Understand outbound SMTP problems in Azure VMs to try to fix your issue.
Meanwhile, for coding, there are some resources that may helps.
Python: Send Email via Office 365
Send email on App Service using Office 365 (O365) in PHP
Sending email from an Azure App Service using an O365 SMTP server in C#
Or using some packages directly like python-o365: GitHub and PyPI.
Finally, there is a service named SendGrid which be used for email service. You can use it to send mail in your scenario on Azure, please refer to the offical tutorial to know How to Send Email Using SendGrid with Azure (C#). For Python, you can code via its REST API or sendgrid python library.

Python sending e-mail with SMTP without authentication

I'm making a script that notifies people about some pending tickets in JIRA. These notifications are sent by e-mail, I already got the notification to trigger, but I'm having problems sending the emails.
I can send them using gmail but when I tried to do it with my official account (the one that the company gave me) I am not able to send them. IT guys already provided me the 'localhost' because they use SMTP relays and the port, but they keep telling me that I should start SMTP without authentication, I'm not very sure of how to do this.
The example I found on internet was this:
import smtplib
fromaddr = 'Axel.Sa#mydomain.com'
toaddrs = ['Axel.Sa#mydomain.com']
msg = '''
From: {fromaddr}
To: {toaddr}
Subject: testin'
This is a test
.
'''
msg = msg.format(fromaddr=fromaddr, toaddr=toaddrs[0])
server = smtplib.SMTP('localhost:25')
server.starttls()
server.ehlo("mydomain.com")
server.mail(fromaddr)
server.rcpt(toaddrs[0])
server.data(msg)
server.quit()
But I keep getting this error, If someone can tell me the proper way of sending emails by SMTP without authentication I will be very grateful.
Check this stack:
How to send an email without login to server in Python
change your smtplib.SMTP('localhost:25') to smtplib.SMTP('localhost', 25)

Postfix sending email as root#localhost.foo.com

We deployed sentry on premise. We have no problems sending email through the applications. Sender shows "tail#foo.com" in the email.
However, there is celery worker that sends out emails, since the sender is "roo#localhost.foo.com" emails are bounced.
I have tried configuring generic and added hosname in main.cf. But didnt work.
My problem is postfix is sending emails as root#localhost.foo.com not as tail#foo.com.
What do I need to change or do to have the emails sent as tail#foo.com?
You can use masquerade_domains setting as a workaround using this command:
$ postconf 'masquerade_domains = $mydomain'
masquerade_domains (default: empty)
Optional list of domains whose subdomain structure will be stripped off in email addresses.

Can someone please explain this code to me (Python [Sending Emails])

I have found the following code below from a website explaining how to send emails (Hotmail/live) using python. I can understand some of the code but most of it is totally confusing. For example what does, s.starttls() mean/do and also msg.as_string(); was that defined earlier or what does it do? Please help me out because i want to understand this code (i want to make a gui application version of this soon).
Guide me through this please....
P.S --> I'm only 16 so please make it sound as understandable as possible.
The Code:
import email
import smtplib
msg = email.message_from_string('warning')
msg['From'] = "example#hotmail.fr"
msg['To'] = "example#hotmail.fr"
msg['Subject'] = "helOoooOo"
s = smtplib.SMTP("smtp.live.com",587)
s.ehlo()
s.starttls()
s.ehlo()
s.login('example#hotmail.fr', 'pass')
s.sendmail("example#hotmail.fr", "example#hotmail.fr", msg.as_string())
s.quit()
I'm sorry to tell you, but this is not exactly the place to get a coding lesson. This is a place to ask for precise coding questions. So it's very likely that your question will get flagged and I will be amongst those who will ask for closing it. But…
…I've been there, learning to code at your age at a time when Internet was just a small portion of what it is today. So let me give you some insight and pointers.
The code you pasted is very straightforward, given you know a bit of programming and understand the SMTP protocol.
When you send a mail, you're doing a TCP connection to a server on ­— usually — the port 25 (but 587 in your case). There you have to follow a precise protocol to have the server understand what you want to do. This protocol has been defined by the RFC821.
The same way you follow a protocol when you meet someone (which is like "hi!", then shake hands, then say "how're you doing?") before asking a question, the server does the same:
EHLO example.org
MAIL FROM alice#example.org
RCPT TO bob#example.org
DATA
Date: Fri, 21 Aug 2015 23:12:29 +0000
From: Alice <alice#example.org>
To: Bob <bob#example.org>
Go RTFM!
--
Bob
.
Where you say to the server:
Hi! I'm Alice!
I Want to send a message to Bob!
Can you tell him to go RTFM?
Which is what you're actually doing in your code.
Now let's get more on the programming side of things. First of all, you import modules, one for handling an email the other one for the smtp connection:
import email
import smtplib
to understand how to use it, you can launch the python REPL on the command line and do dir(email) to show its objects, and help(email) to get the integrated help:
python
>>> import email
>>> dir(email)
['Charset', 'Encoders', 'Errors', 'FeedParser', 'Generator', 'Header', 'Iterators', 'LazyImporter', 'MIMEAudio', 'MIMEBase', 'MIMEImage', 'MIMEMessage', 'MIMEMultipart', 'MIMENonMultipart', 'MIMEText', 'Message', 'Parser', 'Utils', '_LOWERNAMES', '_MIMENAMES', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', '_name', 'base64MIME', 'email', 'importer', 'message_from_file', 'message_from_string', 'mime', 'quopriMIME', 'sys']
>>> help(email)
Help on package email:
NAME
email - A package for parsing, handling, and generating email messages.
FILE
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/email/__init__.py
MODULE DOCS
http://docs.python.org/library/email
…
the objects are all the actions and objects being developed by the community that you can use. And the help is giving a bit more insight, as well as the URL you want to visit to know more about what you can do with it, along with examples.
Then, you create a mail message:
msg = email.message_from_string('warning')
msg['From'] = "example#hotmail.fr"
msg['To'] = "example#hotmail.fr"
msg['Subject'] = "helOoooOo"
on which you setup the Subject, From and To lines, as well as the body, in the SMTP protocol that would look like:
From: example#hotmail.fr
To: example#hotmail.fr
Subject: helOoooOo
warning
.
Then you open a connection to the SMTP server of Live.com:
s = smtplib.SMTP("smtp.live.com",587)
that connection gives an object knowing the details of where you're connecting to, and offers methods you can apply on that connection. The methods are actions you can do on it, i.e.:
You say "hi!"
s.ehlo()
Then, you start encrypting the communication:
s.starttls()
it is doing the "encryption handshake" protocol on your smtp connection, so that further communication is now "secure", i.e. nobody can read your password by looking at the packets between your computer and the server.
You can read more about it there:
https://docs.python.org/3/library/smtplib.html#smtplib.SMTP.starttls
And you can read its source code here:
https://hg.python.org/cpython/file/3.4/Lib/smtplib.py#l654
You say "hi!" again, not only because you're very polite, but because you switched from unencrypted to encrypted, your mail server is expecting you to say hi again:
s.ehlo()
You identify yourself, so that live.com knows that you're who you're prentending to be:
s.login('example#hotmail.fr', 'pass')
so there you want to change for your actual account's email address and password
Then, you send your mail to/from example#hotmail.fr:
s.sendmail("example#hotmail.fr", "example#hotmail.fr", msg.as_string())
In the first part of my answer, I told you about the "SMTP" protocol, where you have to say who you are and who you want to talk to? well this is what you're doing here. This method will translate into:
MAIL FROM example#hotmail.fr
RCPT TO example#hotmail.fr
And then, your mail object is a python "instance" that has no sense for your smtp server. You have to have it translated from the form that your mail server can understand, which is full text. You can have a look at what it is by doing in the python REPL:
python
>>> import email
>>> msg = email.message_from_string('warning')
>>> msg['From'] = "example#hotmail.fr"
>>> msg['To'] = "example#hotmail.fr"
>>> msg['Subject'] = "helOoooOo"
>>> print(msg)
<email.message.Message instance at 0x10dcb1560>
which means "python knows about an object called msg, which is made thanks to the class email.message.Message and lives at the memory address 0x10dcb1560".
But if you do the following, then you'll get the mail you'll send:
>>> print(msg.as_string())
From: example#hotmail.fr
To: example#hotmail.fr
Subject: helOoooOo
warning
Which is what actually you give to the SMTP handler instance that takes care of sending it properly.
And because you're polite, you're telling the server you're leaving by saying "bye", instead of leaving silently.
s.quit()
All that being said, I can only advice you to open a few books, take some online courses and most importantly do practice, starting from the simple stupid and boring examples to stuff way more complex. Start first by doing textual interfaces before doing graphical ones which are a bit more complex.
Here are a few pointers:
Official python tutorial: https://docs.python.org/3.5/tutorial/
Another tutorial: http://sthurlow.com/python/
You might want to follow online courses as well:
https://www.coursera.org/course/programming1
https://www.coursera.org/course/interactivepython1
https://www.udemy.com/python-for-beginners/
https://www.codecademy.com/tracks/python
just to give a few ones.
As your code suggests, it looks like you might be french, then I can only advice you to read the excellent book on algorithmic written by a former teacher I had, which is teaching programming principles and thinking without being tied to a programming language:
Passeport pour l'argorithmique object, Jean-Pierre Fournier
HTH
So message_from_string('warning') takes in a string and puts into a message object structure. Then you set the From, To, Subject. You then define the SMTP address and port it uses. ehlo() just tells the server that you're going to be sending a message through it. starttls() says that from now on, all the data sent will be sent through TLS, so all your passwords will be safe and encrypted. You login, send the mail to and get the message you previously set the first line, back as a string to send off. Then you close the SMTP connection.
All of the resources you need can be found at the Python Standard Library: 18.1 Email and 20.12 smtplib.
I will do a line by line explanation focusing on the two lines you mentioned. (Skipping the imports)
msg = email.message_from_string('warning')
Creating a message object with value "warning"
msg['From'] = "example#hotmail.fr"
msg['To'] = "example#hotmail.fr"
msg['Subject'] = "helOoooOo"
Designates Sender, Reciever, and Subject of message
s = smtplib.SMTP("smtp.live.com",587)
This sets up a mail client (specifically an SMTP client session object) that can send mail to any internet machine with an an SMTP or ESMTP listener daemon. (This includes all big emails like gmail, yahoo, aol, etc.)
s.ehlo()
This identifies you as a server using EHLO and sets up a lot of default attributes needed to send your message.
s.starttls()
Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted.
s.ehlo()
Good practice to put after the previous command because the information is now encrypted.
s.login('example#hotmail.fr', 'pass')
Logs in with (username, password)
s.sendmail("example#hotmail.fr", "example#hotmail.fr", msg.as_string())
Sends the message (From, To, Msg). The msg.as_string() simply means you want the message format to be a string.
s.quit()
Terminates session.

Categories

Resources