How to automatically print HTML attachments in outlook 32bit or 64bit - vba

When a customer places an order from the site, an email with an attached file (HTML format) is sent to the management for his order and we want to print it automatically through Outlook, I searched all over the internet but the script I did not find a suitable one for this job.
Can anyone create a VBA Scriptfor Outlook 2016 32bit or Outlook 2019 64bit that can be saved and printed directly when a new email contains an attachment?
I tried many scripts but they did not help me and could not print the HTML file automatically, I made all the necessary settings but the script does not work.

To handle incoming emails in VBA you can handle the NewMailEx event of the Outlook Application class. The NewMailEx event fires when a new message arrives in the Inbox and before client rule processing occurs. 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 returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item.
After an item is retrieved you could check the Attachments.Count property and decide whether to print it or not.
To print the content of the incoming email item you can use the MailItem.PrintOut method which prints the Outlook item using all default settings. The PrintOut method is the only Outlook method that can be used for printing.
But to print the attached HTML file you need to save it on the disk first and then call the print verb against the saved file, for example:
Sub PrintFile(FileToPrint as string)
Dim objShell
Set objShell = CreateObject("Shell.Application")
If FileToPrint = "" Then
GoTo MainLoop
Else
Debug.Print FileToPrint
objShell.Namespace(0).ParseName(FileToPrint).InvokeVerb ("Print")
End If
MainLoop:
Debug.Print "No files to print"
End Sub

Related

Reprocessing Outlook Undelivered Mail

I have an Exchange mailbox with a bunch of Outlook ReportItem Undelivered messages. I am attempting to reprocess the undelivered messages via an Outlook VBA script by invoking the "SendAgain" operation on the ReportItem messages. My issue is that the ReportItem does not have a send method, so I have no way of actually sending the reprocessed messages. I am using the following code to go through the messages:
Dim objApp As Outlook.Application
Dim objNameSpace As NameSpace
Dim journalAlertInbox As Folder
Dim objInspector As Inspector
Dim resendItem As ReportItem
Set objApp = CreateObject("Outlook.Application")
Set objNameSpace = objApp.GetNamespace("MAPI")
Set journalAlertInbox = objNameSpace.Stores.Item("thestore").GetDefaultFolder(olFolderInbox)
For Each folderItem In journalAlertInbox.Items
If TypeOf folderItem Is ReportItem Then
folderItem.Display
Set objInspector = folderItem.GetInspector
objInspector.CommandBars.ExecuteMso "SendAgain"
Set resendItem = Application.ActiveInspector.CurrentItem
Set objInspector = resendItem.GetInspector
''how do I send the item that is now displayed?
''resendItem.Close olSave
folderItem.Close olDiscard
End If
Next folderItem
I thought I might be able to save the displayed message as a draft, however If I uncomment the resendItem.close olSave line this results in a message in my Outlook Drafts folder of type ReportItem. I can open up the saved draft message it the Outlook GUI and click the send button, but I do not see a way to actually invoke the send operation programmatically. Examining the message in drafts shows it to be of type ReportItem, which does not have a .Send method.
How can I invoke the "Send" operation on the Report Item? I can clearly see the "Send" button, but there seems to be no programmatic way of actually clicking it.
OOM does not expose any functionality that allows to link a ReportItem object to the original MailItem, and, generally, there might not be any kind of link between the two. The best you can do is to retrieve PR_ORIGINAL_SEARCH_KEY MAPI property (or PR_REPORT_TAG, which includes both the search key and the store/Sent Items folder entry id) using ReportItem.PropertyAccess.GetProperty and try to find a matching message in the Sent Items folder. You can see these properties in OutlookSpy (I am its author).
Keep in mind that OOM does not allow to search on the binary (PT_BINARY) properties in Items.Find/Restrict.
If using Redemption is an option (I am also its author), it exposes RDOReportItem.FindOriginalItem method.
Once you have the original item, you can make a copy and try to send it again.
The ReportItem doesn't represent the original item which is failed to be sent. Also it doesn't contain any relationship with the original mail item, so you will not find any property or method available in the Outlook object model. Your existing solution looks good.
You may also try using the ReportItem.GetConversation method which obtains a Conversation object that represents the conversation to which this item belongs. So, you may try getting the previous item from the conversation, it could be the original item which has been submitted.

Reply, with template, using properties of original mail

I work at a Company that gets requests we filter in terms of
being eligibile for financing from our financing partner
requiring more information from the enquirer
There is a lot of monotonous work, in copy pasting email replies.
I looked into creating a Quick Action in Outlook, but because our mother company does not allow certain freedoms, like the Font has to be specifically Segoe Ui Light etc. I could not use this, so I thought about writing a macro.
I intended for a macro button to:
Open a new Reply email, replying to all in the original mail.
In this new email text body, use a template email that I already made and saved as a template. (This way it saved the Font, size and other formatting.)
Put in the original Sender and CC'ed mail addresses as well as the Subject from the original mail.
And then display the email, so I could make edits if I wanted to before sending.
Sub ReplyGewerbeanmeldung()
Dim origEmail As MailItem
Dim replyEmail As MailItem
Set origEmail = Application.ActiveWindow.Selection.Item(1)
Set replyEmail = Application.CreateItemFromTemplate(" "C:\Users\XYZ\AppData\Roaming\Microsoft\Templates\ReplyGewerbeanmeldung.oft"\ReplyGewerbeanmeldung.oft")
replyEmail.To = origEmail.Sender
replyEmail.CC = origEmail.CC
replyEmail.Subject = origEmail.Subject
replyEmail.HTMLBody = replyEmail.HTMLBody & origEmail.Reply.HTMLBody
replyEmail.Display
End Sub
First of all, it seems you need to correct the file path to the template message. The following string is not a valid file path:
" "C:\Users\XYZ\AppData\Roaming\Microsoft\Templates\ReplyGewerbeanmeldung.oft"\ReplyGewerbeanmeldung.oft"
Try to use the following string instead:
Set replyEmail = Application.CreateItemFromTemplate("C:\Users\XYZ\AppData\Roaming\Microsoft\Templates\ReplyGewerbeanmeldung.oft")
You can read more about that in the How To: Create a new Outlook message based on a template article.
Anyway, creating items from a template will not preserve the original message body. Moreover, in Outlook you will not get any visual appearance that a particular items was replied. So, you need to call the ReplyAll method on the original item in Outlook to avoid this artefacts in Outlook.
You can create a new mail item, but only for copying the message body response which is required to paste into the reply. The NameSpace.OpenSharedItem method can be used to to open iCalendar appointment (.ics) files, vCard (.vcf) files, and Outlook message (.msg) files. You may consider using it instead of creating a new item based on the template to grab the message body from there.

Why do Embedded Image Sizes Evaluate to 0 in Outlook VSTO Add-In?

We are building a VSTO Outlook Add-In that scans an outgoing mail message for attachments to alert users and noticed some unexpected behavior.
Considering the following ways of adding a file to an Outlook mail message:
A file attachment
Screen Shot
Screen Clipping
Mail Signature file
All four are recognized as attachments when the Item Send event fires:
Private Sub Application_ItemSend(ByVal Item As Object, ByRef Cancel As Boolean) Handles Application.ItemSend
In the following code example:
For Each attachment As Outlook.Attachment In Item.Attachments
'do some stuff like check attachment size
Next
We are checking for small embedded images in a signature file that don't want to notify the user of.
In the following cases:
Screen Shot
Screen Clipping
Mail Signature file
We've noticed that when the added files are embedded images (not attachments), we don't see a correct size property for the image using:
attachment.Size
IE: Say we are sending an Outlook email that has:
One Attachment.
One Screen Shot.
One Signature File with one image in it.
Our code seems to recognize the correct number of attachments, however if we check the attachment size for a screen shot or a signature file image, the attachment size property always evaluates to 0, which we're think is due to the fact that the file doesn't exist on disk and the attached file does.
For Each attachment As Outlook.Attachment In Item.Attachments
if attachment.size > 755 then
'ignore the image
end if
Next
Is there a way to check the image size in VB.Net or do we need to save the file off to a temp directory in order to do this?
EDIT
Outlook Spy Troubleshooting steps:
New Mail Message
Inserted screen shot and signature file:
OutlookSpy->IMessage
IMessage window blank (below)
Close IMessage window.
Re-Open IMessage Window
Inserted (attached) files appear (below)
8. Double Clicked on attachment
Selected Inspector Button
Current Item:
Browse:
Attachments:
Browse:
IEnumVariant:
I suspect that the differences between steps 4 and 7 may be due to the fact that Outlook may have saved a draft of the email message?
ADDITIONAL EDIT
Code added to save mail message before checking signature/embedded image size:
'convert generic object to Outlook.MailItem object.
Dim objMailItem As Outlook.MailItem = CType(Item, Outlook.MailItem)
'Save message
objMailItem.Save()
'quick check to see if message is saved (it is)
Dim saved As Boolean = objMailItem.Saved()
For Each attachment As Outlook.Attachment In objMailItem.Attachments
'all items still evaluate to 0.
If attachment.Size >= 20 Then
'do some stuff
End If
Next
Thanks.
Attachment size (which includes raw binary data as well as the per-attachment properties) is updated by the store provider when the mesage is saved. Make sure you call MailItem.Save first.
We ended up using Outlook Spy (awesome tool..) to find the PR_ATTACH_SIZE property:
Then set up using MS schema as follows:
'property access to get attachment sizes
Const PR_ATTACH_SIZE As String = "http://schemas.microsoft.com/mapi/proptag/0x0E200003"
Also great info from this SO Post.
Then iterated through our attachment collection as follows to find our attachment sizes:
For Each attachment As Outlook.Attachment In Item.Attachments
attSize = CType(attachment.PropertyAccessor.GetProperty(PR_ATTACH_SIZE), Integer)
if attSize.size > 755 then
'ignore the image
end if
Next
Thanks..

Moving an attachment from an email into an Outlook folder

I'm trying to take attachments from mails received and move them into a folder within Outlook.
I can move the entire message, and I've also worked out how to save the attachments to a drive, but neither of these things is what I'm looking for.
I was looking at something along the lines of the below, but I'm guessing there is no Attachment.Move similar to MailItem.Move.
Sub test1()
Dim olFolder As MAPIFolder
Set olFolder = Application.GetNamespace("MAPI").Folders("Mailbox - Test").Folders("Inbox")
Dim Item As Object
For Each Item In olFolder.Items
Set oMail = Item
For Each att In oMail.Attachments
att.Move Application.GetNamespace("MAPI").Folders("Enterprise Connect").Folders("Test")
Next
Next
End Sub
The attachments do not exist as standalone entities in folders - what you see if a message with a single attachment. The item's message class is IPM.Document.* - when you double click on an item like that, Outlook is smart enough to open the attachment instead of showing an inspector. Take a look at such an item with OutlookSpy (I am its author - click IMessage and Item buttons).
Outlook Object Model does not allow to create DocumentItem objects directly. But you can create a regular MailItem object, add an attachment using MailItem.Attachments.Add, then reset the MessageClass property appropriately - e.g. for a ".txt" attachment, look up HKEY_CLASSES_ROOT\.txt registry key, read the default value, append it to message class (IPM.Note.txtfile).
If using Redemption (I am also its author) is an option, it exposes the RDODocumentItem and allows to create document items directly (see the examples).
The Attachment class doesn't provide such methods. You need to save the attached file to the disk and then re-attach it anew to another Outlook item.
You may find the Getting Started with VBA in Outlook 2010 article helpful.

Create a mail object and track it down in sent folder

I need to create a mail via VBA, send it, and then export a .msg file of the sent mail to be archived (I know, it's weird, but that's what the boss asked for).
Creating the mail is straightforward:
Set OLK = Outlook.Session
Set ML = OLK.Createitem olMailItem
With ML
.Recipients.add "somebody#somedomain.com"
.Subject = "Great mail you have there"
.Body = "It would be a shame if somebody couldn't archive it"
End with
ML.Send
Problem is, after sending the mail is moved in the sent folder and the ML object points to nothing.
I could use the .saveas method before sending, but then the saved file is the unsent version, which can be edited and sent again.
How can I trace the mail in the sent folder?
The "brute force" way I found out implies saving the ConversationIndex before sending
IDX= ML.ConversationIndex
and then scan all the items in the sent folder for it:
For each ML in OLK.Session.GetDefaultFolder(olFolderSentMail).Items
If ML.ConversationIndex = IDX Then ML.SaveAs HomeDir & "\" & OutFileName: Exit For
Next
but it isn't exactly a smooth work.... (and may fail if some smartass replies to the automatic mail, even if nobody should)
Max,
You can handle the ItemAdd event of the Items class which belongs to the Sent Items folder. It is fired when one or more items are added to the specified collection.
In the ItemAdd event handler you can check out whether a particular item should be saved or not. For example, you can add a user property before calling the Send method. See the UserProperties class for more information.
Set myProp = myItem.UserProperties.Add("MyPropName", olText)
Be aware, the MailItem class provides the SaveSentMessageFolder property which allows to set a Folder object that represents the folder in which a copy of the e-mail message will be saved after being sent. So, you can assign a custom folder to save them.
You can add a user property (MailItem.UserProperties.Add), but that would cause the message to be sent in the TNEF format unless the UseTnef property (DASL name http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8582000B) is explicitly set to false.
You can set a named MAPI property using PropertyAccessor.SetProperty - just pick your custom GUID and property name. E.g.
ML.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/string/{3ADE3813-37A9-49C9-AD84-D49C8FF5D660}/MyOwnProp", "SomeValue")