python poplib get attachment - python-2.7

I am trying to access POP3 email server. I will be polling messages and downloading attachments for each one of them. I can successfully login and get the messages but cannot figure out how to actually get the attachment, which I would need to parse later.
I'm thinking I could save to tmp dir until I process it.
Here's what I got so far:
pop = poplib.POP3_SSL(server)
pop.user(usr)
pop.pass_(pwd)
f = open(file_dir, 'w')
num_msgs = len(pop.list()[1])
for msg_list in range(num_msgs):
for msg in pop.retr(msg_list+1)[1]:
mail = email.message_from_string(msg)
for part in mail.walk():
f.write(part.get_payload(decode=True))
f.close()
This is code I pieced together from the examples I found online but no solid example of actually getting the attachment. The file I'm writing to is empty.
What am I missing here?

Please see a complete example below.
Import poplib and parser
import poplib from email import parser
A function to return a connection to the pop server:
def mail_connection(server='pop.mymailserver.com'):
pop_conn = poplib.POP3(server)
pop_conn.user('someuser#server')
pop_conn.pass_('password')
return pop_conn
A function to fetch the mail:
def fetch_mail(delete_after=False):
pop_conn = mail_connection()
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
messages = ["\n".join(mssg[1]) for mssg in messages]
messages = [parser.Parser().parsestr(mssg) for mssg in messages]
if delete_after == True:
delete_messages = [pop_conn.dele(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
pop_conn.quit()
return messages
Then a function to save the attachments as files. NB, the allowed mimetypes; you could have a list of them, such as:
allowed_mimetypes = ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
and so on.
def get_attachments():
messages = fetch_mail()
attachments = []
for msg in messages:
for part in msg.walk():
if part.get_content_type() in allowed_mimetypes:
name = part.get_filename()
data = part.get_payload(decode=True)
f = open(name,'wb')
f.write(data)
f.close()
attachments.append(name)
return attachments

I know this is an old question, but just in case: The value you're passing to email.message_from_string is actually a list of the contents of the email, where each element is a line. You need to join it up to get a string representation of that email:
mail = email.message_from_string("".join(msg))

Related

Django - Update or create syntax assistance (error)

I've followed the guide in the queryset documentation as per (https://docs.djangoproject.com/en/1.10/ref/models/querysets/#update-or-create) but I think im getting something wrong:
my script checks against an inbox for maintenance emails from our ISP, and then sends us a calendar invite if you are subscribed and adds maintenance to the database.
Sometimes we get updates on already planned maintenance, of which i then need to update the database with the new date and time, so im trying to use "update or create" for the queryset, and need to use the ref no from the email to update or create the record
#Maintenance
if sender.lower() == 'maintenance#isp.com':
print 'Found maintenance in mail: {0}'.format(subject)
content = Message.getBody(mail)
postcodes = re.findall(r"[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][A-Z]{2}", content)
if postcodes:
print 'Found Postcodes'
else:
error_body = """
Email titled: {0}
With content: {1}
Failed processing, could not find any postcodes in the email
""".format(subject,content)
SendMail(authentication,site_admins,'Unprocessed Email',error_body)
Message.markAsRead(mail)
continue
times = re.findall("\d{2}/\d{2}/\d{4} \d{2}:\d{2}", content)
if times:
print 'Found event Times'
e_start_time = datetime.strftime(datetime.strptime(times[0], "%d/%m/%Y %H:%M"),"%Y-%m-%dT%H:%M:%SZ")
e_end_time = datetime.strftime(datetime.strptime(times[1], "%d/%m/%Y %H:%M"),"%Y-%m-%dT%H:%M:%SZ")
subscribers = []
clauses = (Q(site_data__address__icontains=p) for p in postcodes)
query = reduce(operator.or_, clauses)
sites = Circuits.objects.filter(query).filter(circuit_type='MPLS', provider='KCOM')
subject_text = "Maintenance: "
m_ref = re.search('\[(.*?)\]',subject).group(1)
if not len(sites):
#try use first part of postcode
h_pcode = postcodes[0].split(' ')
sites = Circuits.objects.filter(site_data__postcode__startswith=h_pcode[0]).filter(circuit_type='MPLS', provider='KCOM')
if not len(sites):
#still cant find a site, send error
error_body = """
Email titled: {0}
With content: {1}
I have found a postcode, but could not find any matching sites to assign this maintenance too, therefore no meeting has been sent
""".format(subject,content)
SendMail(authentication,site_admins,'Unprocessed Email',error_body)
Message.markAsRead(mail)
continue
else:
#have site(s) send an invite and create record
for s in sites:
create record in circuit maintenance
maint = CircuitMaintenance(
circuit = s,
ref = m_ref,
start_time = e_start_time,
end_time = e_end_time,
notes = content
)
maint, CircuitMaintenance.objects.update_or_create(ref=m_ref)
#create subscribers for maintenance
m_ref, is the unique field that will match the update, but everytime I run this in tests I get
sites_circuitmaintenance.start_time may not be NULL
but I've set it?
If you want to update certain fields provided that a record with certain values exists, you need to explicitly provide the defaults as well as the field names.
Your code should look like this:
CircuitMaintenance.objects.update_or_create(default=
{'circuit' : s,'start_time' : e_start_time,'end_time' : e_end_time,'notes' : content}, ref=m_ref)
The particular error you are seeing is because update_or_create is creating an object because one with rer=m_ref does not exist. But you are not passing in values for all the not null fields. The above code will fi that.

Python - Text does not appear in code-triggered email sent if string is result of a formula

I am attempting to write a program that sends an email from Gmail, with a body of text that includes real time stock quotes. I am using a module to get stock quotes in string format (this works), and I wrote a function to send an email from gmail. The message_send function is only working if I give it a simple string. It is not working if I pass it the aapl_string variable. See code below:
from yahoo_finance import *
import smtplib
def message_send(messagebody):
fromaddr = 'REDACTED'
toaddrs = 'REDACTED'
msg = messagebody
# Credentials (if needed)
username = 'REDACTED'
password = 'REDACTED'
# The actual mail send
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
aapl = Share('AAPL')
aapl.refresh()
price_aapl = aapl.get_price()
aapl_string = "The current price of AAPL is: " + price_aapl
print(aapl_string)
message_send(aapl_string)
Any ideas why the email sends, but contains blank text when using aapl_string as the argument for the message_send function?
Thanks!
You could do
message_send("The current value is %s" %price_aapl)
and that should make it work :)
I'm assuming price_aapl is an integer, and if that's the case then that is your whole problem. This is due to the inability of being able to add integers to strings so what you could do is use a format string.
ex:
aapl_string = "The current price of AAPL is: %d" % price_aapl
the %d is a placeholder for the integer price_aapl.
You can look here -> http://www.diveintopython.net/native_data_types/formatting_strings.html
for more information on formatting strings in python.

How to retrieve attributes of message written to a SQS queue using Boto?

I have the following code snippet.
conn = boto.sqs.connect_to_region(region)
q = conn.lookup('myqueue')
m = Message()
m.set_body('My Message')
data = {"UserID": {"data_type": "Number","string_value": "11111"}}
m.message_attributes = user_data
q.write(m)
Using this, I have successfully written the attributes I wanted with the message. Now, I wanted to retrieve it. I have tried
msg.message_attributes
But I have got an empty dictionary only.
Is this the way to retrieve it? Or am I wrong somewhere?
I have got the answer to my question.
For this you must have retrieved the message like this
attributes = ['UserID']
msgs = q.get_messages(message_attributes=attributes)
Will get msgs as a list. And let msg be msgs[0]
Then the message attribute can be retrieved by the following code.
msg.message_attributes['UserID']['string_value']

AT commands with pyserial not working with receiving sms

This is a code snippet written in python to receive sms via a usb modem. When I run the program all I get is a status message "OK"., but nothing else.How do I fix the issue to print the messages I am receiving?
import serial
class HuaweiModem(object):
def __init__(self):
self.open()
def open(self):
self.ser = serial.Serial('/dev/ttyUSB_utps_modem', 115200, timeout=1)
self.SendCommand('ATZ\r')
self.SendCommand('AT+CMGF=1\r')
def SendCommand(self,command, getline=True):
self.ser.write(command)
data = ''
if getline:
data=self.ReadLine()
return data
def ReadLine(self):
data = self.ser.readline()
print data
return data
def GetAllSMS(self):
self.ser.flushInput()
self.ser.flushOutput()
command = 'AT+CMGL="all"\r'
print self.SendCommand(command,getline=False)
self.ser.timeout = 2
data = self.ser.readline()
print data
while data !='':
data = self.ser.readline()
if data.find('+cmgl')>0:
print data
h = HuaweiModem()
h.GetAllSMS()
In GetAllSMS there are two things I notice:
1) You are using self.ser.readline and not self.Readline so GetAllSMS will not try to print anything (except the first response line) before the OK final response is received, and at that point data.find('+cmgl')>0 will never match.
Is that just the problem?
2) Will print self.SendCommand(command,getline=False) call the function just as it were written as self.SendCommand(command,getline=False)? (Just checking since I do not write python myself)
In any case, you should rework your AT parsing a bit.
def SendCommand(self,command, getline=True):
The getline parameter here is not a very good abstraction. Leave out reading responses from the SendCommand function. You should rather implement proper parsing of the responses given back by the modem and handle that outside. In the general case something like
self.SendCommand('AT+CSOMECMD\r')
data = self.ser.readline()
while ! IsFinalResult(data):
data = self.ser.readline()
print data # or do whatever you want with each line
For commands without any explicit processing of the responses, you can implement a SendCommandAndWaitForFinalResponse function that does the above.
See this answer for more information about a IsFinalResult function.
where you are having problems is here in your GetAllSMS function. Now replace my GeTALLSMS function with yours and see what happens
def GetAllSMS(self):
self.ser.flushInput()
self.ser.flushOutput()
command = 'AT+CMGL="all"\r' #to get all messages both read and unread
print self.SendCommand(command,getline=False)
while 1:
self.ser.timeout = 2
data = self.ser.readline()
print data
or this
def GetAllSMS(self):
self.ser.flushInput()
self.ser.flushOutput()
command = 'AT+CMGL="all"\r' #to get all messages both read and unread
print self.SendCommand(command,getline=False)
self.ser.timeout = 2
data = self.ser.readall() #you can also u read(10000000)
print data
thats all...

Facebook problem + django

I am trying to write a facebook app where user can see the status history of his friends.
Everything seems to work fine until I try to save the status information in my DB.
here is code :
class UserStatus(models.Model):
facebookid = models.IntegerField()
time = models.IntegerField()
status_msg = models.CharField(max_length = 2000)
#facebook.require_login()
def canvas(request):
# Get the User object
user, created = FacebookUser.objects.get_or_create(id = request.facebook.uid)
user_lastname = request.facebook.users.getInfo([request.facebook.uid], ['last_name'])[0]['last_name']
query = "SELECT time,message FROM status WHERE uid=%s" % request.facebook.uid
result = request.facebook.fql.query(query)
So result give me all the information of the status.
so my problem is its give error when I try to save it.
userstatus = UserStatus()
for item in result:
userstatus.facebookid = request.facebook.uid
userstatus.time = item.time
userstatus.msg = item.message
userstatus.save()
error:
Errors while loading page from application
Received HTTP error code 500 while loading
So how can I fix this.
thanks.
First you should check if you are getting results from this,
result = request.facebook.fql.query(query)
Make sure that the results are in correct format required by your model ( uid is integer, time is integer and message is string.
Again make sure that result is a valid python object and not a JSON string/Object.
Remember python is not fully compatible with JSON so if result is JSON then do this to convert it to python Object,
import simplejson
result = simpljson.loads(result) # if result was a JSON string
result = simpljson.loads(simplejson.dumps(result)) # if result was a JSON object
Check if now result is a list of dictionaries { "time" : 123456, "messaage": "xyz"}.
for item in result:
userstatus = UserStatus()
userstatus.facebookid = request.facebook.uid
userstatus.time = item["time"]
userstatus.msg = item["message"]
userstatus.save()
And you should not have any errors now.