Print original email when it is undelivered - vba

I'm using MS Office 2016 Desktop App on Windows 10.
I didn't find any success searching online and also contacting MS Outlook Support to find that there is no easy way to achieve it except VBA script.
We send individual mail having an attachment, to a huge bulk of people. (I'm fine with this.)
I want when an email is not sent successfully (because of incorrect email address or other reason), to perform some action on the original email (not the undeliverable mail notice).
Possible action could be printing the mail and its attachments to some other email.
I want this as it is burdensome to print individual emails from around 1000s of emails daily.
MS Outlook rules don't provide the condition for 'when email undelivered' or similar. Can this be achieved with VBA script?

In theory - yes. Firstly, you need to make sure you get the actual NDR and the object type is ReportItem. That shouldn't be a problem if you are sending through Exchange, but if you are sending through POP3/SMTP account or if the NDR is delivered as a regular plain text message from the target server rather than your own Exchange Server, all bets are off.
The various report properties are stored in the recipient table of the NDR items. Unfortunately, ReportItem in OOM does not expose the Recipients collection like it does for MailItem. You can get NDR information from the Body property, but unfortunately OOM has a bug (left unfixed for a few years now) that causes ReportItem,Body to return meaningless garbled text. See Extract text string from undeliverable email body to Excel.
In most cases, you would be able to extract the message id of the original message (that caused in the NDR) from the PR_TRANSPORT_MESSAGE_HEADERS property (take a look at an NDR with OutlookSpy - I am its author - click IMessage button). You can access that property using ReportItem.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x007D001F"). You can then try to extract the In-Reply-To MIME header and use it to search for the original message in the Sent Items folder using Items.Find on the PR_INTERNET_MESSAGE_ID property (DASL name http://schemas.microsoft.com/mapi/proptag/0x1035001F). And here lies another problem - it is possible that the item in the Sent Items folder will not have that property: it is set automatically by Exchange, but the item in teh Sent Items folder in the cached store might not have it because most likely the item in never synchronized (this is due to bandwidth optimization trick by Outlook), so you might have to open the folder in the online mode using the MAPI_NO_CACHE flag, which OOM won't let you use - it is either Extended MAPI (C++ or Delphi) or Redemption (I am also its author - any language). See https://stackoverflow.com/questions/45952523/what-is-the-vba-property-for-server-folder-contains-x-itmes for an example.

Related

Changing the email text in an "have server reply using specific reply" action with vba

I have the following rule in outlook:
have server reply using specific reply rule
My aim is now, to change the email text that gets send by the action with a vba script. The data we send out as a respones changes daily, so at the moment we have to change it by hand. I tried now many things, but don't come really to the possibility to change the text with vba.
I'm also not sure if i can get it with olRuleActionServerReply (because it has no item oder similar when i watch this action) or with olRuleActionTemplate...
I'm happy for any hint in this situation. Thank you in advance!
I tried to find anything in the documentation but didn't find anything helpful.
There is no way to use a dynamic reply with a different text used for the message body. You need to set up a different rule for that or handle incoming emails in VBA without rules involved.
For example, you could handle the NewMailEx event of the Application class where you could check the incoming email and prepare the response and send it automatically. This event fires once for every received item that is processed by Microsoft Outlook. The item can be one of several different item types, for example, MailItem, MeetingItem, or SharingItem. The EntryIDsCollection string contains the Entry ID that corresponds to that item. Use the Entry ID to call the NameSpace.GetItemFromID method and process the item.

Is there a way I can programmatically attach a large file to an outlook message despite it exceeding the server size limit?

A quick note in case you come upon this question hoping for a solution.... there isn't one. Sadly sometimes one has to accept that the right answer to one's question is "You can't do that".
I am hoping there is something I can do here to ensure that attaching a large file to an Outlook.MailItem works exactly the same as doing so manually.
To be precise... when a user composes an email in Outlook and they attach a file that is too large to the email, Outlook will happily attach the file to the email. Instead of simply refusing to do so, it will attach the file and a message will appear in the Inspector:
However....
When coding a similar action you would get access to an Outlook.MailItem and you would invoke the .Add method on its .Attachments object
oMailObject.Attachments.Add("<path to a file that is way too big here>")
The problem is that that action fails. An error is thrown
"The file you're attaching is bigger than the server allows. Try putting the file in a shared location and sending a link instead."
Yes, we can obviously catch the error and then show a message to the user. That's what we're currently doing. It would, however, be nicer if there were a way I can prevent it from raising the error so it would still attach the file to the MailItem, and then when I show the inspector to the user they would see the same thing they would see if they had attached the attachment manually.
Is there an option on the MailItem to prevent it raising an error? Something in the Attachments.Add method? Any suggestions?
The Attachments.Add method doesn't provide anything for that.
You may consider adjusting the maximum size of the attachments in Outlook. Regular mail profiles can be configured using the windows registry keys.
HKEY_CURRENT_USER\Software\Microsoft\Office\<x.0>\Outlook\Preferences
HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\ x.0 \Outlook\Preferences
There you can add a value type: DWORD
Value name: MaximumAttachmentSize
Value data: An integer that specifies the total maximum allowable attachment size. For example, specify 30720 (Decimal) to configure a 30-MB limit. Specify a value of zero (0) if you want to configure no limit for attachments.
Exchange accounts require configuration on the Exchange side, read more about that in the Microsoft Exchange Server email account configuration section.
You can read PR_MAX_SUBMIT_MESSAGE_SIZE MAPI property (DASL name is "http://schemas.microsoft.com/mapi/proptag/0x666D0003") from the store (use Store.PropertyAccessor.GetProperty) - it returns the size in kB - prior to sending the message. This property is Exchange-specific.

Attachments missing on the EWS server for draft email saved via Outlook OfficeJS

I am using the Office.context.mailbox.item.saveAsync method for saving a draft email. This method returns itemId which I later use to make a call to the EWS server to retrieve the email eml content, but the returned eml content is missing some of the attachments.
This is only happening on the Desktop App (Outlook 2013) with cache mode enabled. When using Outlook on the Web it works correctly.
I am using ews-java-api to retrieve the email from the EWS.
Is there a way to know when the email saving is finished?
I can't use the Office.context.mailbox.item.saveAsync.makeEwsRequestAsync because of the 1MB response limitation.
In Cached mode it will take time for the item to sync up to the server. People usually poll until the data they want is there.
Also, they can write a custom property, and check for that property to make sure their item is up to date if necessary.
You can find some details about custom property here: Client Extension Message Object Protocol, Mail App Custom Properties and Mail App Accesses Custom Properties
Is there a way to know when the email saving is finished?
If the following: "Is there a way to know when the email saving is finished?" is your question, than the answer is No. You may try the ugly solution, when you use sub-sequential EWS query with Id you've got from saveAsync in the loop and wait for success. This may take, depend on environment, from a few seconds to like half a minute easily. Not sure if your customers (users) will wait for so long, when add-in finally respond.
You may get more information from the topic: App for Outlook: EWS request failed with item Id returned by item.saveAsync on compose new message
EDIT:
Simple GetItem request can be used as follow ...
<GetItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<ItemShape>
<t:BaseShape>IdOnly</t:BaseShape>
</ItemShape>
<ItemIds><t:ItemId Id="' + itemId + '"/></ItemIds>
</GetItem>
The request should return ChangeKey if item was created on exchange.

Reading email body of email with RMS protection using MAPI

I have a C++ Oulook plugin that reads outgoing emails (during ItemSend event) and analyzes them. When sending an email and adding RMS permission, the PR_BODY_W property of the outgoing email contains (instead of the real body):
This message is protected with Microsoft Information Protection. You can
open it using Microsoft Outlook, which is available for iOS, Android,
Windows, and Mac OS. Get Outlook for your device here:
https://aka.ms/protectedmessage.
Microsoft Information Protection allows you to ensure your emails can't be
copied or forwarded without your permission. Learn more at https://microsoft.com/rms.
The real body is retrieved successfully with Outlook Object Model by calling MailItem.Body property.
However, is there a way to read the body using MAPI and not OOM?
The text in PR_BODY really is the real body. However, when Outlook finds an RMS attachment on a message, it substitutes what it finds in that attachment for the real body. The OOM masks this behavior for you. Using MAPI, you'll have to do the decode yourself.
RMS attachments in Outlook/Exchange messages is governed by [MS-OXORMMS]: Rights-Managed Email Object Protocol. Specifically, you're interested in Opening a Rights-Managed Email Message.
Here's the general outline:
Grab PidNameRightsManagementLicense from the message.
Locate attachments with a message class of "rpmsg.message"
Unzip the attachment following RFC 1950
Continue unpacking data from the attachment following the protocol doc.
...
Knowing that all of this is governed by OXORMMS, we can find the following project on GitHub which might be instructive: https://github.com/damico/test-inflate-rms.

How do I check for the presence of a valid email (digital) signature attached to an Outlook MailItem (email message)?

Is there any way to
Retrieve a digital signature attached to a MailItem using VBA?
Verify its validity using VBA?
I'm pretty much limited to VBA in this regard. I've tried inspecting the Sender and MailItem objects but I can't see anything about a Signature object.
Outlook always represents signed/encrypted messages as regular "IPM.Note MailItem" objects. It goes as far as returning a fake IMessage MAPI interface from the MailItem.MAPIOBJECT property.
You can see this in OutlookSpy (I am its author) - select a signed message, click IMessage button on the OutlookSpy ribbon. PR_MESSAGE_CLASS will be IPM.Note. Select the PR_ENTRYID property, right click, select IMAPISession::OpenEntry. You will get back the real message with PR_MESSAGE_CLASS = IPM.Note.SMIME.MultipartSigned. You can see the attachment that contains the data.
You are pretty much limited to Extended MAPI (C++ or Delphi only) or Redemption (I am its author - any language - it wraps Extended MAPI) if you want to distinguish signed/encrypted message from the regular ones. Redemption exposes RDOEncryptedMessage object. You can retrieve it from RDOSession.GetMessageFromID using the entry id retrieved from MailItem.EntryID property in OOM.