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.
Related
The recipient address and the distro lists do not immediately resolve. Outlook is smart enough to recognize the email addresses, but it doesn't recognize my distro list. At least not immediately.
I'm using Office 365 if that matters.
from win32com.client import Dispatch
outlook = Dispatch('Outlook.Application')
Mail_Item = outlook.CreateItem(0)
# This sends no problem
# Mail_Item.To = 'first.last#company.com'
# This does not send
Mail_Item.To = 'Contact_Group_Test'
Mail_Item.Subject = "Subject_text"
Mail_Item.Body = "Body_text"
Mail_Item.Recipients.ResolveAll()
Mail_Item.Send()
While troubleshooting I used Mail_Item.Display() to see the message. After a few seconds it resolves all my addresses, including the contact group. HOWEVER, the contact group itself still doesn't work despite this.
If you couldn't solve, you can try smtplib.
import smtplib
sender = 'from#fromdomain.com'
receivers = ['to#todomain.com']
message = """From: From Person <from#fromdomain.com>
To: To Person <to#todomain.com>
Subject: SMTP e-mail test
This is a test e-mail message.
"""
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
except SMTPException:
print "Error: unable to send email"
If you will send mail from outlook account, you have to write smtp-mail.outlook.com instead of localhost
mtbenj's answer may work for others. I'm just choosing to go the win32com route because of my organization.
For whatever reason using 'Test', and I'm assuming, any one-word contact list takes ~5 seconds to resolve. I counted after the .Display() popup came up. Naming it 'Test_' didn't do it for me either.
I decided to try one named 'Test_Test'. After calling .Recipients.ResolveAll(), it works perfect.
So use an underscore and multiple words.
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
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)
I'm trying really hard to check why this is happening but not really sure if its on gmail's server side or in a part of the script I'm using.
The problem is that I'm trying to send an email to a mailing list (I have found many posts explaining how to include various emails but none explaining if there is a limitation or workaround to send it to a single email which contains multiple addresses).
In this case I want to send the email to many different people which make part of the BI team of our company (bi#company.com), normally sending an email to this address will result in everyone from the team getting the email, but I can't manage to make i work, and I don't want to include all emails in the list because there are too much and it will have to be manually changed every time.
When I try this with another single person email it works perfectly
import smtplib
sender = 'server#company.com'
receivers = ['bi#company.com']
q = ""
message = """From: Error alert <Server-company>
To: BI <bi#company.com>
Subject: Error e-mail
%s
""" % q
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Successfully sent email"
except SMTPException:
print "Error: unable to send email"
Alright. I found out why this was not working in my organization. Hopefully this can help someone else out. The outlook groups were setup to only work from an internal email address.
Sending emails programmatically, may use a relay method, which has no authentication. As such the email will never go through. The fix is to have the Network ops people (or exchange group) at your company turn on receiving external emails. The emails will then go through.
make recivers a list of emails you want to send:
example:
recivers = ['a#gmail.com','b#gmail.com,...]
try like this:
import smtplib
from email.mime.text import MIMEText
sender = 'server#company.com'
receivers = ['a#company.com','b]#company.com'....]
server = smtplib.SMTP('smtp#serv.com',port)
server.starttls()
msg = MIMEText('your_message')
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(receivers)
server.login('username','password')
server.sendmail(sender, recipients, msg.as_string())
server.quit()
I finally decided to stick to writing the full list of email addresses inside the list. Apparently if mailing lists are managed locally the re distribution of the emails cant be done.
I have a cronjob that runs a python script to periodically send an email with status updates to me. On the weekend I prefer this to work via text, so I send it to myphonenumber#vtext.com. This works fine, except the 'from' address is incorrect when it goes to the phone. It shows correctly when it is sent to a regular email address. For some reason when it goes through a text it shows the 'from' address as "myusername#servername.wndowsdomain.local". This may simply be a verizon text message thing specifically, but if possible I'd like to figure out how to fix it as I hope to add some reply functionality to this tool.
The machine that the script is on is running Ubuntu 12.04.
Here is the simple python function I have that sends the email:
def sendMail(to,text):
msg = MIMEMultipart('alternative')
msg['Subject'] = "Weekend Report"
msg['From'] = 'servername#mydomain.com'
msg['To'] = to
msg.attach(MIMEText(text,'plain'))
p = Popen(["/usr/sbin/sendmail", "-t"], stdin=PIPE)
p.communicate(msg.as_string())
Would I be better off using something like smtplib and a gmail account or something perhaps?
Sendmail: Setting envelope sender
You may try to set "envelope sender" address too (sender address used in SMTP session).
p=Popen(["/usr/sbin/sendmail","-t","-i","-fservername#mydomain.com"],stdin=PIPE)
Comment: I have added missing -i command line option unrelated to setting envelope sender.