-1

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()
ThatGuyRussell
  • 1,361
  • 9
  • 18
  • To find out about s.starttls, note that s is defined as smtplib.SMTP() so I googled 'smtplib.SMTP' and in the first hit (https://docs.python.org/2/library/smtplib.html) searched for 'starttls' until found its definition at https://docs.python.org/2/library/smtplib.html#smtplib.SMTP.starttls and which says 'Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted.' The same process can find out about 'email.message_from_string' - just google it, take the first or second hit and search it for that function. –  Aug 20 '15 at 23:17

3 Answers3

6

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:

You might want to follow online courses as well:

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:

HTH

zmo
  • 24,463
  • 4
  • 54
  • 90
  • Thanks that was very informative! I understand enough of the code to write a GUI application now. Also i'm not french i'm English (Canadian). But thanks anyways! –  Aug 21 '15 at 16:32
  • The `MAIL FROM` and `RCPT TO` arguments should properly be in ``. – tripleee Aug 23 '15 at 05:56
1

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.

heinst
  • 8,520
  • 7
  • 41
  • 77
0

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.

ThatGuyRussell
  • 1,361
  • 9
  • 18