VBA - Outlook message ID - using to identify preeviously processed messages - vba

If processing emails in an outlook mailbox, is it possible to use some kind of ID to record the last message processed avoiding the need to iterate through all messages every time?
I'm trying to write a quick 'attachment stripper' to free up mailbox space and don't want to have to iterate through every message in a mail folder each time the code is ran. At a pinch I could use the mail folder name and the message date, but what happens if a folder is renamed, or messages moved? (Besides, I REALLY hate dates!!! formats to start with, and I have recently experienced randomly changing environment settings in my work environment - a citrix remote desktop - so now have a near phobia of the damn things!)
I was hoping there was some kind of message ID I could use but can see neither the MAPI ID nor the Outlook Mail ID being suitable here (though I could well be wrong). Is there a means of doing this?

If you need to avoid reprocessing previously processed emails, you have no recourse but to either record the email's unique identifiers externally for later checking, or flagging emails with a specific value (such as adding a Category, setting a flag, adding a custom field, setting an internal field, etc.) to avoid processing them later.

Related

Send and Save specific emails. Not a sentitem event listener

Edit: I am just going to use an eventlistener. I would delete the post but maybe somebody will find a non eventlistener way to save a sent mailitem before it is received in the sent item inbox.
Issue: Outlook won't receive VBA sent emails until macro completes. If I use wait, sleep, while loops or anything else, the email will not be received. I can't use a Sent Items event listener because I only want specific emails saved to the folder, not all. I individually know how to save from sent items, I know how to send messages. The issue is the delay between sending the email with VBA and it appearing in my Sent Items box. If I saveas before waiting, the email that is saved is the previous email, but if you try to wait, the sent items folder never updates. Any ideas or simple solutions. I might just be dumb.
I have read every forum but haven't found a solution, I had it running at another company but no longer remember how. I use a macro to send very specific emails and do lots of other tasks. I would then like to grab the email I just sent and save it to a folder using vba. The issue is receiving the email in my "Sent Items" folder is delayed. If I try to capture it or wait to receive it, my code never finishes. All solutions I see in the forums are a Sent Item listener / Inbox event listeners, but I don't need that, I know which emails to trigger it on.
One way or another, you'd need to wait for some event to fire, be that Items.ItemAdd on the Sent Items folder, or SyncObject.SyncEnd on the SyncObject - message submission is asynchronous, so no amount of sleep or while loops would help you. You cannot just stop your VBA script and resume it when the message is actually sent since your code is running on the main Outlook thread - if your script pauses, so does Outlook.
You can try using the NameSpace.SendAndReceive method which initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile. Note, calling the SendAndReceive method is asynchronous. SendAndReceive provides the programmatic equivalent to the Send/Receive All command that is available when you click Tools and then Send/Receive.
If you don't need to synchronize all objects, you can use the SyncObjects collection object to select specific objects. For more information, see NameSpace.SyncObjects.
In your VBA code you may also consider using the DoEvents function which yields execution so that the operating system can process other events. DoEvents passes control to the operating system. Control is returned after the operating system has finished processing the events in its queue and all keys in the SendKeys queue have been sent (if any).
DoEvents is most useful for simple things like allowing a user to cancel a process after it has started, for example a search for a file.
Solution, not the solution or used in the past but I settled.
Basically just the event listener solution that everyone in all the forums suggest. I created a separate folder in my Sent Items and use myNameSpace.GetDefaultFolder to set that folder for the VBA sent items.. I send the emails only to that folder and I added the listener to only that folder. This allows me to separate the Sent items and this specific VBA sent emails and then to save them automatically. I am still looking for a way to save the sent Mail Item before the Sent Item Inbox shows it, but I have given up at this point. Thanks for everyone's help. If I find the better answer, I will try to post it along with the code.

Can ConversationID change for existing item in conversation?

We are writing Outlook VSTO add-in and save info about mail items in database. Some features are relying on conversations in Outlook, so we save ConversationID in the database to detect that all messages are from the same thread.
Recently I found that at some point conversationID is changed for the entire conversation! So I have first message with ID
5E2C809C8D7E4BEBA402613311DD8C7B
And then suddenly it becomes
347B0DEB35C68E1EE882EFABE4BCC373
for the next messages. And when I select previous messages they also have this 347 id.
It seems that it broke when I answered an e-mail with changed subject (and it gets out of thread) or after I answered from Win10 mail client. But I can't reproduce this anymore.
Does anyone know in which cases this can happen?
Conversation index can change if the "Thread-Index" MIME header is missing from a message in the conversation. But it will not change for the existing older messages in a conversation. For that to happen, each and every one of them would need to be updated, and if that happened, you should see the updated last modified date.

NServiceBus Central Repository

I am currently researching the possibility of using NServiceBus for one of our applications. The current application takes large text files and parses the details into a database. The users perform various operations on the file content, approve the changes, and finally release the updated file. When the file is released, various other services need to do something with that file data (drop file in ftp folder, email customer, bill customer).
From what I read services should be autonomous and not share data, except via messages. I like that concept, however in my case I am wondering if it is practical. Some of these files can contain up to a million records.
So my question is, should each service (operations, billing, emailer) all have their own database and table for storing this file data, and move the data via the DataBus? Or should I be more pragmatic and only send the fileID in the message which references a central file table?
Thanks for any guidance you can offer.
There are a couple of things that one should not do with a service bus:
move masses of data
perform queries
large ETL operations
You are certainly able to do all these things but you will probably be left disappointed. The messaging to enable some of these operations is fine, though. Your idea of sending the FileID is definitely the way to go.
As an example: I have previously implemented an e-mail sending service. This service can send attachments but these can be large. So instead of including the attachments in the messages I stored the attachments on a shared folder and sent a SendEMailCommand message that also included the unique attachment ids that need to be sent with the e-mail. The e-mail service would then pick up the attachments from the shared folder. After the service successfully sent the mail an EMailSentEvent message would be published.

Can this scenario lead to a race condition?

Suppose that we have a message passing system using mailboxes. When sending to a full mail box or trying to receive from an empty one, a process does not block, instead, it gets an error code back. The process responds to the error code by just trying again, over and over, until it succeeds. Does this lead to race condition?
First at all I recommend to review what a race condition means.
If the mailbox system handles "atomicity" when receiving/retrieving emails, there is no race condition. Your app may loop forever trying to retrieve a message but it isn't a race condition.
Now, let's imagine that the mailbox system does not use any kind of locking mechanism. If at the same time, you are trying to read if a new message exists, a new message is arriving to the mailbox, you may read an uncompleted message because is still reaching.
In the best case you get the uncompleted message but usually a crash occurs because of an invalid pointer, etc.
The situation you describe wouldn't in itself lead to a race, though the actions you take in response to the error could, e.g pushing a "detected this mail box is empty" message to the empty mail box. Do that from two threads, you could easily end up with two mails.

Re-getting POP3 messages

I am using Peter Huber's POP3 client to connect to gmail and download messages.
The inboxes being accessed are transactional inboxes used only for code-access. That is, a message comes in with a order file attached, code will process it and then delete the message. One stipulation of the code though was a DEBUG flag, which if set would prevent the code from deleting the message so that you can run the program again later without the debug flag and reprocess the message. So, in my code I have
If Not Arguments.Debug Then pop.DeleteEmail(eid)
This works fine. Problem is, even when not deleting the message, running the program a second time will not re-retrieve the message, even though if I login to gmail and look at the inbox, it is still there. The only way I can get the program to see the message again is to forward the message back to the same inbox. But in Peter's code I do not see anywhere where he is keeping track of seen messages between sessions.
Is this something that is done on gmail's end? Refusing to deliver a message to the same client a second time? If so, is there any way I can change my gmail account so that it will always show all messages in the inbox to a client when retrieving the list of messages, even ones already "seen"? I don't see anything in the gmail settings screen.
UPDATE: I tried adding a method to send a RSET command to the server, as per this comment on the codeproject page. I then call my new Reset() method after retrieving my messages but before disconnecting, ... but I still have the same problem.
Okay... found a "sort of" answer after reading through pages of the comments on the codeproject project.
According to this comment, the RSET command does not actually do anything when you are dealing with gmail's servers.
The "answer" is to prepend your username with the string "recent:", so instead of logging in with [myaccount#gmail.com] you log in with [recent:myaccount#gmail.com]. Rather hackish, ... but it works.