Timestamp of Outlook emails using Python - python

Is it possible to use Python to extract timestamps from received email? I'm using the following code but to no avail:
messages = ap.Items
message = messages.GetNext()
receipt = message.ReceivedTime.date()
for i in messages:
print(receipt)
I only get one date published repeatedly for each email. (i.e., 2021-11-22, 2021-11-22, 2021-11-22.......)
Any help will be much appreciated.

Well, of course - you only retrieve ReceivedTime once:
for i in messages:
print(i.ReceivedTime.date())

Related

Is it possible to get recent 10 emails using Gmail-api?

For now, I can use gmail api to get all UNREAD emails or all emails in INBOX.
GMAIL.users().messages().list(userId='me', labelIds=['UNREAD', 'INBOX']).execute()
Because getting all the emails could be annoying, I was wondering is it possible to get only the recent 10 UNREAD emails from gmail api?
Thanks for any hint that will allow me to do such thing.
The documentation tells us that we need to pass maxResults and set it to 10:
GMAIL.users().messages().list(userId='me', labelIds=['UNREAD'], maxResults=10).execute()
Go through this doc
You can query using the advanced search options.
You may use
newer_than:
Example: newer_than:2d
Search for messages older or newer than a time period using d (day), m (month), and y (year)
GMAIL.users().messages().list(
userId="me",
labelIds=["UNREAD", "INBOX"],
maxResults=10,
q="newer_than:6d"
).execute()

Maildir - open latest email and reply to sender

I've configured postfix on the email server with .forward file which saves a copy of email and invokes a python script. These emails are stored in Maildir format.
I want to use this Python script to send a reply to the sender acknowledging that the email has been received. I was wondering if there is any way I can open/access that e-mail, get the header info and sender address and send email back.
I looked at several examples of Maildir functions of Python, but they mostly add/delete e-mails. How can I open the latest e-mail received in Maildir/new and get the required information?
The program I have so far:
md = mailbox.Maildir('/home/abcd/Maildir')
message = md.iterkeys().next()
#print message
#for msg in md:
# subject = msg.get('Subject',"")
# print subject
print message
sender = message.get('From',"")
print sender
When I execute this, I do get the sender name. But It is rather the oldest email arrived in Maildir/new folder not the latest one.
Also, if I use get_date function, what if two (or more) e-mails arrive on the same day?
The MaildirMessage's method .get_date() gets you the timestamp of the
message file on disc. Depending on your filesystem, this may have anywhere between two second and nanosecond accuracy. The changes of two messages giving the same value with .get_date() are vastly smaller than when this actually returned a date only.
However if the message files were touched for some reason the return from .get_date() would not be relevant at all. Dovecot e.g. explicitly states that a files mtime should not be changed.
There are several dates associated with a MaildirMessage:
The arrival time timestamp, as encoded in the name of message (the part before the first dot, these are "whole" seconds). If the part
between the first and second dot has a segment of the form Mn than n is the microsecond arrival time, and be used to improve the resolution of the timestamp.
The timestamp of the file on disc
The 'Date:' header field as set by the sending program (or added by some
MTA)
The dates added by intermediate MTA in the 'Received:' header field
The last of these might not be available e.g. if you and the sender are on the same mail server. The third can be easily faked/incorrect (ever got spam in your inbox dated many years ago?). And the second is incorrect if the file ever got touched.
That leaves selecting on the first option:
d = {}
for name in md.keys():
d.setdefault(int(name.split('.', 1)[0]), []).append(name)
result = sorted(d.items())[-1][1]
assert len(result) == 1 # might fail
msg = md.get_message(result[0])
If you are lucky result is a list with a single item. But this value has only second resolution, so you might have multiple emails and then you have to decide on how to decide which message to select based on one of the other values (e.g. by sorting using the files timestamp .get_date()) or just select the first, randomly select one. (If you have the log file, you can search for the result messages' keys in there to determine which one arrived latest).
If you wouldn't convert to int, and have old emails (i.e. before 2001-09-09 03:46:40) a string comparison would probably not give you the message with the latest arrival time.
Some hints for this:
You can open a Maildir with the mailbox.Maildir class (see the Documentation for mailbox)
You can iterate over all the mails in a Maildir via the method itervalues
Now you get all the mails in the Maildir. One of them is the most recent one.
The mails are objects of the class MaildirMessage, which is a subclass of Message. For these classes, also a documentation exists (on the same page as mailbox, currently)
With the method "get_date" on those objects, you can find out, which one is the most recent one. You still have to select it yourself.
So much as beginners help: A little bit you should also do by yourself.
You should make yourself familiar with the Python documentation - I agree, that it is not easy to find the right packages and how to use them, but you can try them directly in the Python shell.
Ok, here another code snippet:
newest = None
for message in md.itervalues():
if newest == None or message.get_date() > newest.get_date():
newest = message
# now newest should contain the newest message
Did not see your last question: get_date does not only contain the date, but also the time, because it gives the number of seconds since (normally) 1970.

Receiving "role" and/or "affiliation" with message in SleekXMPP

Apologies for the amateur question. I'm just learning Python and I'm fumbling around this XMPP bot script using XMPP.
I have a bot built using the MUC bot example from SleekXMPP: http://sleekxmpp.com/getting_started/muc.html
Where my bot differs from the example is my script creates a SQLite database and on each group_message event, parses the XML to retrieve the nick and message body text and write it to the database with a timestamp.
Here is the part of my bot that's recording the msg output from the XMPP channel:
def groupchat_message(self, msg):
if msg['type'] in ('groupchat'):
raw = str(msg) # Save raw XML as a string in the database for debugging purposes
timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
fromuser = str(msg['from']) # Convert "from" attribute to string so it can be split
author = fromuser.split('/')[1] # Split "from" attribute to remove channel address leaving only nick behind
body = msg['body']
msginsert = [timestamp, author, body, raw] # Database input list to be handed to placeholders.
db.execute("INSERT INTO messages VALUES (?,?,?,?)", msginsert) # "?" placeholder is REQUIRED for automatic database sanitization.
dbconn.commit()
print("[",timestamp,"]",author,": ",body, sep='')
else:
print(msg)
The print statements are just for debugging purposes so I can watch the messages tick by in the terminal so I know the script is running.
In the recorded information I would like to also include the user's role or affiliation in the XMPP channel so admins and moderators can be singled out. This is what I'm having trouble wrapping my head around. It seems like I should be able to do it based on the SleekXMPP stanza docs but I'm having trouble figuring out how I get from the message XML to the role/affiliation information.
How can I take the information provided in the message XML and get back the role and/or affiliation of the user who posted that message?
For reference, this is the raw XML output from the XMPP channel for messages:
<message to="username#example.com" from="channelname#channels.example.com/User Nick" id="1453" type="groupchat">
<body>This is the message body text</body>
<x xmlns="jabber:x:event">
<composing />
</x>
</message>
The role/affiliation isn't included in the message, it is part of the state of the chat.
As a reminder, XMPP has three different stanzas that get send: <message>, which you had as an example, <iq>, which are used to retrieve or set things and <presence>, which indicates the presence of things. The role/affiliation information is included in a presence stanza. For example in the first presence stanzas your client receives to inform it of who is present in the room already, see Example 21 from XEP-0045 (Multi-User Chat). Your client also receives new presence stanzas whenever someone's nickname, role or affiliation changes or when they leave the room.
You should make sure you store this information yourself, because SleekXMPP doesn't do it for you. This can be done by creating a dictionary that stores, for every nickname, their role and one for their affiliation. On presence changes you should make sure to update this information. Then you can use those dictionaries in your message handler to log their role/affiliation.
So something like:
def __init__(...):
self.roles = dict()
self.affiliations = dict()
self.add_event_handler(""groupchat_presence"", self.muc_presence)
...
def muc_presence(self, presence):
nick = presence['muc']['nick']
self.roles[nick] = presence['muc']['role']
self.affiliations[nick] = presence['muc']['affiliation']
This is the general idea, you'll need to do some more work to make it handle nickname changes and people leaving the room properly.

Add adding if/else to python parser

I have a snippet of code here that uses gmail POP to to parse messages coming from a text message (1xxxxxxxxx7#vtext.com). I want the parser to be able to search for multiple strings in the message, and run code accordingly per each different string. Right now, the parser is set to find sequences with 'Thank you' but I don't know how to expand on this as I am extremely new to python. My code is as follows:
import poplib
from email import parser
pop_conn = poplib.POP3_SSL('pop.gmail.com')
pop_conn.user('xxxxxxxxxxxxx')
pop_conn.pass_('xxxxxxxxxxxxx')
#Get messages from server:
messages = [pop_conn.retr(i) for i in range(1, len(pop_conn.list()[1]) + 1)]
# Concat message pieces:
messages = ["\n".join(mssg[1]) for mssg in messages]
#Parse message intom an email object:
messages = [parser.Parser().parsestr(Thankyou) for Thankyou in messages]
for message in messages:
print 'Data Received'
pop_conn.quit()
The code snippet you provided uses list comprehensions - the most powerful operator in Python. You must learn them if you want to write Python. Here is the beginning.
As of your question - ThankYou here is just a variable name, it means nothing.
It looks like you're struggling with list comprehensions.
#List comprehension
messages = [parser.Parser().parsestr(Thankyou) for Thankyou in messages]
#Equivalent for loop
#Temporary list
temp = []
#Loop through all elements in messages
for Thankyou in messages:
#If parsestr returns True for the current element (i.e. it's the string you're looking for)
if parser.Parser().parsestr(Thankyou):
temp.append(Thankyou)
#Overwrite the messages list with the temporary one
messages = temp
As you can see, the list comprehension is a lot more concise and readable. They're used a lot in Python code, but they're not scary. Just think of them as a for loop that iterates through every element in the given container.
In order to search for more tokens, it looks like you'll need to edit the parsestr() method to return True when you encounter the strings you are looking for.

Gmail IMAP is not returning uids

I am connecting to my gmail account via IMAP to sync some of my emails and parse them. Sometimes I need to download again some emails because I did some kind of fix and now gmail is not returning me the uids of those emails in any way, here is some code to explain myself better:
typ, data = self.connection.uid('search', None, '(SINCE 14-Dec-2012 BEFORE 20-Dec-2012)')
17:05.55 > HJBM3 UID SEARCH (SINCE 14-Dec-2012 BEFORE 20-Dec-2012)
17:05.69 < * SEARCH
17:05.69 < HJBM3 OK SEARCH completed (Success)
('OK', [''])
I have a good bunch of emails on those dates including the ones I want to parse and it doesn't return anything, depending on the date it does return some uids so is not completely broken.
I decided to try if thunderbird synced correctly those emails and it got them no problem.
I am using the python 2.6 imaplib (version 2.58)
Maybe this will help someone so I'll answer it here:
I had in gmail this setting on:
When I changed it to "Do not limit" It worked like a charm.

Categories