5 # Communicate with mail servers
12 class SecureMail(object):
13 def __init__(self
, username
=None, password
=None):
14 """Prompt for login and password, or using stored values if possible, then login."""
18 username
= file(".otplogin").read().strip()
20 username
= raw_input("Username: ")
24 password
= file(".otppass").read().strip()
26 password
= getpass
.getpass()
28 return self
.login(username
, password
)
31 def login(self
, username
, password
):
32 """Login to a Gmail account, IMAP and SMTP server, with login and password."""
34 # IMAP SSL for incoming messages
35 self
.mail_in
= imaplib
.IMAP4_SSL("imap.gmail.com", 993)
37 self
.username
= username
40 typ
, data
= self
.mail_in
.login(username
, password
)
42 raise "Login failure: %s" % (sys
.exc_info(),)
44 assert typ
== "OK", "imap login returned: %s %s" % (status
, message
)
45 print "Logged in:", typ
, data
47 # Always have "Secure" mailbox selected
48 typ
, num_msgs
= self
.mail_in
.select(mailbox
="Secure")
50 raise ("imap select failure: %s %s" % (typ
, num_msgs
) +
51 "The 'Secure' tag doesn't exist. Tag some of your EMOTP messages" +
52 "using a new label, named 'Secure'")
54 # Outgoing mail, SMTP server
55 self
.mail_out
= smtplib
.SMTP("smtp.gmail.com", 25)
56 ret
= self
.mail_out
.ehlo()
57 assert ret
[0] == 250, "SMTP server EHLO failed: %s" % (ret
,)
59 ret
= self
.mail_out
.starttls()
60 assert ret
[0] == 220, "SMTP server STARTTLS failed: %s" % (ret
,)
62 ret
= self
.mail_out
.ehlo()
63 assert ret
[0] == 250, "SMTP server EHLO over TLS failed: %s" % (ret
,)
65 ret
= self
.mail_out
.noop()
66 assert ret
[0] == 250, "SMTP server NOOP failed: %s" % (ret
,)
68 ret
= self
.mail_out
.login(username
, password
)
69 assert ret
[0] == 235, "SMTP server login failed: %s" % (ret
,)
70 print "Logged in to SMTP server: %s" % (ret
,)
72 def get_messages(self
):
76 typ
, all_msgs_string
= self
.mail_in
.search(None, 'ALL')
77 except imaplib
.error
, e
:
78 raise "imap search failed: %s" % (e
,)
80 all_msgs
= all_msgs_string
[0].split()
82 typ
, body
= self
.mail_in
.fetch(num
, "(BODY[])")
83 msg
= email
.message_from_string(body
[0][1])
85 body
= str(msg
.get_payload())
86 subject
= msg
.get("Subject")
87 sender
= msg
.get("From")
88 id = msg
.get("Message-ID")
90 #print 'Message %s\n%s\n' % (num, data[0][1])
91 if "--EMOTP_BEGIN--" not in body
:
94 msgs
.append({"body": body
,
103 """Fetch messages from server."""
104 self
.msgs
= self
.get_messages()
105 return iter(self
.msgs
)
107 def __getitem__(self
, k
):
108 """Lookup a message of a given number. Messages
109 must have been previous fetched from server up by __iter__"""
112 def send(self
, to
, subject
, body
):
113 from_address
= "%s@gmail.com" % (self
.username
,)
114 return self
.mail_out
.sendmail(from_address
,
117 "From: %s" % (from_address
,),
119 "Subject: %s" % (subject
,),
125 self
.mail_in
.logout()
129 ms
= SecureMail("shellreef", getpass
.getpass())
131 for m
in ms
.get_messages():
132 print m
["sender"], m
["subject"]
134 if __name__
== "__main__":