Python Outlook how to handle recall email - python

My project works on emails in Inbox. When process get a "Recall" email it crashes. Recall email does not have subject attribute. I want to write some error handling. I cannot find method to move email to another folder or delete such email from Outlook.
Currently my Code skip such items using method GetPrevious() but the email is still in Inbox
Do you have any ideas how to make 'recall' email disappear from Inbox folder?
obj_emails = obj_inbox.Items
obj_email = obj_emails.GetLast()
if obj_email.MessageClass == 'IPM.Outlook.Recall':
obj_email = obj_emails.GetPrevious()

The Outlook object model doesn't provide anything for handling or generating recall items. You may consider using a low-level API on which Outlook is based on - Extended MAPI. Also you may consider using thied-party components, i.e. wrappers around the low-level API such as Redemption.
Try to play with MFCMAPI to make sure recall items can be easily handled (moved or removed).

Check the Class property - all OOM objects expose it. For the MailItem, it will be 43 (OlObjectClass.olMail). For ReportItem - 46 (OlObjectClass.olReport)

Thank you for your suggestion.
I do not want to complicate the code so I use MessageClass property to catch recall email. Next information will be sent to team to remove such email.
if obj_email.MessageClass == 'IPM.Outlook.Recall':
raise Exception(f"There is a recall email in mailbox. Please remove it from inbox.")

Related

pywin32 - restrict, filtering by a list of potential senders

I need to iterate through every email within my project. I have more than 20000 mails. Therefore i read I need to use the restrict function. I found examples how to restrict to one specific domain
messages = messages.Restrict("#SQL=(urn:schemas:httpmail:SenderEmailAddress LIKE '%#domain.com')")
What do I need to use if have more than 100 domains or multiple (more than 100) Senders I want to use? Would it be a huge restrict function with logical OR connectors with all of the domains or can I input somehow a list into the restrict statement?
EDIT:
and i realized if i run a restrict function with this code, it just shows me with the len(messages) function that there are 0 emails while i can see a bunch of emails in outlook with used domain in the filter. what am i doing wrong?
Typically you would need to use the logical OR operator in the search string. Read more about that in the Filtering Items Using a String Comparison article. Also you may find the following articles helpful:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
But I would recommend handling each domain separately, so you will get Outlook running without freezes and will be able to process items in a logical bunch, especially when you have a hundred of domain names to search for.
If you want to filter out internal senders and only process the senders outside your organization, check the SenderEmailType property - it will be "EX" for the internal senders (assuming you are using Exchange Server) and "SMTP" for the external senders.

UIDs in Gmail - per "folder" or unique per user account?

I recently began using the IMAPClient package in an app where I had previously used imaplib. Something broke after a long time away from the code base (long enough that I was going from Python 2 to Python 3), and I wasn't up for wading into IMAP4 gore (again). I decided to search for something a bit higher level. IMAPClient has, for the most part, been an improvement.
Looking at the docs, I came across this (emphasis mine):
In the IMAP protocol, messages are identified using an integer. These message ids are
specific to a given folder.
I have been using UIDs, operating under the assumption that they are unique across all messages within the account, not per-folder (or per-label for Gmail). This might have been a mistake. Should I instead be considering them to be per-folder? How would that work when talking to Gmail, whose labels aren't exactly the same as folders?
Let me take this from the hypothetical to the concrete. Consider the message with Message-ID <python/cpython/pull/24293#github.com> to which I have applied two labels, polly and python/github. IMAP4 treats these labels as if they are folders. Will Gmail associate one UID or two with that message? If I search first polly, then python/github I assume something representing that message will be returned twice. Will it have the same UID or not?
I found this bit of Gmail-specific IMAP4 documentation, but it seems to be mum on the topic.

How to fix OLE error while parsing emails

I am facing an OLE error while my outlook is being parsed through python using win32com module.
Traceback (most recent call last):
for i, message in enumerate(messages):
pywintypes.com_error: (-520879857, 'OLE error 0xe0f4010f', None, None)
I believe this is due to a network connection which might be restarting after a particular amount of time.
inbox= win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").Folders["Inbox"]
messages = inbox.Items
for i, message in enumerate(messages):
Iterating through all items in the folder is not really a good idea:
for i, message in enumerate(messages):
Instead, I'd suggest getting a subset of items and process them in a batch. For example, you can use the Find/FindNext or Restrict methods to get a subset of items (according to your conditions) and process them. Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Also, you may consider using the AdvancedSearch method of the Application class. The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.

How to validate, store and execute user rules?

In my application:
there are users.
emails come in to the system.
users can use a web browser to define filter rules for their inbound emails.
Filter rules are of the general form "if field operator value/regex then do action X with parameter Y"
I need to:
validate the user rules (which will be created by the user with
an HTML page of dropdowns and text fields)
store the user rules in some appropriate format (maybe as Python
source?)
execute the rules within my Python processing script.
My question is:
is this is a "solved problem"? I want to avoid reinventing the wheel and it sure seems like this or something conceptually very similar must have been done before. Maybe there's even some sort of open source library or application that already does it.
If it is not a solved problem, can anyone suggest an effective way to validate, store and execute the rules? I'm guessing somehow it makes sense for the rules to be Python statements but I sure as hell don't want to write a language syntax parser.
UPDATE: Although the users will be very technical/likely developers, I still want the entry of rules to be tightly constrained to the general form specified above. very similar to the email rules you probably have in your email client right now. For example "if subject contains "subscribe" then send reply email to fromaddress"
UPDATE 2: The filtering rules will not only be on the email fields but also on other non email stuff, for example, the content of an attachment, or evaluation of a custom field that relates to the email but is not part of the email, generated by my system.
Any input valued.
I'm using Python 3.

Use python to detect outlook auto-responder before sending message

I have found many resources on inspecting the headers in an email to detect whether or not the message was sent using an auto-responder. I'm looking to detect that an auto-responder is configured before any contact is made.
Why I think this is possible: In outlook, if you add a recipient from the address book it will show their auto-responder message above the "To:" line before even clicking send.
Goal: I would like to pass a list of employees to a function and return a binary list of whether or not they are in the office based on auto-responder on/off status.
Some bad psuedo-code (please excuse the mixing of classes and lists, it's just for a simple example).
list = ['Ted Jones', 'Michael Brickman', 'This name', 'That name']
for employee in list:
if employee.autoresponse != '':
employee.inoffice = 0
output = [0,1,1,1] #-- So, Ted Jones is out of the office
I'm certainly not stuck on this style of output, just trying to be specific. I need some sort of ordered list or something to tie Name -> In/Out of office
I would like to stay in Python if possible, but am interested to hear other solutions.
Is there anyway to do this? Maybe using win32com or pyad? If a resource for this information exists please let me know... I was unable to find it among the 'check the headers' muck.
You will have to either use Outlook's automation interface, or do the same thing Outlook does (presumably via MAPI or AD), or do the equivalent with some other API.
You can use win32com for the first of the three.
When you add a recipient to the To list in Outlook, it's getting a Recipient object, which has an AutoResponse property, which Outlook will show you.
The easiest (if maybe not the cleanest) way to get a Recipient object through the OOM is to do the exact same thing: create a dummy message, add a recipient, then look at its properties. Items have Recipients objects, which have an Add method that takes an identifier and returns a Recipient (and adds it to the item's recipients, of course).
So, the code should look something like this (untested because I don't have a Windows/Outlook box connected to Exchange here):
session = win32com.client.Dispatch("Mapi.Session")
session.Logon(MY_PROFILE)
outlook = win32com.client.Dispatch("Outlook.Application")
message = outlook.CreateItem(0) # olMailItem
autoresponses = {}
for name in names:
recipient = message.Recipients.Add(name)
autoresponses[name] = recipient.AutoResponse
You can of course combine that into a one-liner dict comprehension, but I thought this might be clearer. Also, you probably want to discard the message so Outlook doesn't end up sticking your leftover garbage in Drafts or something, and you probably want some error handling, and you may need to use a separate message for each recipient to make it easier to recover from errors and move on, and so on… But this, together with the MSDN and win32com docs, should be enough to get you going.
Of course this only works if name resolves to a server mailbox; if you give a local-only name or address, or external-only address, you'll just let a local address book entry or a bare email entry, neither of which have an AutoResponse. But that's exactly the same as in Outlook, so presumably it's expected.
Also note that the first time your script does anything that tries to access the Address Book, unless the user has deliberately turned off the default safety features, he will get a popup like "A program is trying to access e-mail addresses you have stored in Outlook. Do you want to allow this?"

Categories

Resources