IN THE SPOTLIGHT: MDE to MDB Conversion Service
(also supports: ACCDE to ACCDB, ADE to ADP, etc)
IN THE SPOTLIGHT: Access Database Repair Service
An in-depth repair service for corrupt Microsoft Access files
IN THE SPOTLIGHT: vbWatchdog
VBA error handling just got easier...
" vbWatchdog is off the chart. It solves a long standing problem of how to consolidate error handling into one global location and avoid repetitious code within applications. "
- Joe Anderson,
Microsoft Access MVP
Meet Shady, the vbWatchdog mascot watching over your VBA code →
(courtesy of Crystal Long, Microsoft Access MVP)
IN THE SPOTLIGHT: vbMAPI
An Outlook / MAPI code library for VBA, .NET and C# projects
Get emails out to your customers reliably, and without hassle, every single time.
Use vbMAPI alongside Microsoft Outlook to add professional emailing capabilities to your projects.
IN THE SPOTLIGHT: Code Protector
Standard compilation to MDE/ACCDE format is flawed and reversible.
The examples provided here are code snippets. Please understand that vbMAPI is a large library, and to give complete examples to every possible usage scenario is simply not possible. The most commonly requested examples are provided here.
Some of the examples, such as A simple SendMail function are more complete than others. For most of the examples, you will need to add your own error handling. Please use these snippets as a general guide, and adjust them to suit your requirements.
Feel free to contact us should you require any assistance in implementing these snippets, or if you need help in implementing something that is not listed here.
vbMAPI offers the ability to wrap an Outlook MailItem object (from the Outlook object model) into a "safe" vbMAPI object to avoid the security prompts very easily.
We do this by using the vbMAPI_Init.NewOutlookWrapper method. This makes it easy to incorporate vbMAPI into existing projects that use the Outlook Object Model - simply use the vbMAPI wrapper when you want to avoid the security warnings (e.g. for the MailItem.Send method, or to access the address book).
Example:
Dim OutlookApp As Object Dim Item As Object ' Create a new Outlook.MailItem object (late bound example) Set OutlookApp = CreateObject("Outlook.Application") Set Item = OutlookApp.Session.GetDefaultFolder(4).Items.Add Item.To = "address" Item.Subject = "Test Subject" Item.HTMLBody = "My <b>HTML</b> message body..." ' Create a vbMAPI wrapper to call the Send method (to avoid prompts) Dim SafeItem As vbMAPI_MailItem Set SafeItem = vbMAPI_Init.NewOutlookWrapper(Item) SafeItem.Send
Dim OutlookApp As Object Dim Item As Object ' Create a new Outlook.MailItem object (late bound example) OutlookApp = CreateObject("Outlook.Application") Item = OutlookApp.Session.GetDefaultFolder(4).Items.Add Item.To = "address" Item.Subject = "Test Subject" Item.HTMLBody = "My <b>HTML</b> message body..." ' Create a vbMAPI wrapper to call the Send method (to avoid prompts) Dim SafeItem As vbMAPI_MailItem SafeItem = vbMAPI_Init.NewOutlookWrapper(Item) SafeItem.Send()
// This example requires a reference to the Outlook type library using Outlook = Microsoft.Office.Interop.Outlook; Outlook.Application OutlookApp = new Outlook.Application(); // Create a new Outlook.MailItem object Outlook.OlDefaultFolders FolderType = Outlook.OlDefaultFolders.olFolderOutbox; Outlook.MAPIFolder Folder = OutlookApp.Session.GetDefaultFolder(FolderType); Outlook.MailItem Item = Folder.Items.Add(Type.Missing); Item.To = "address"; Item.Subject = "Test Subject"; Item.HTMLBody = "My <b>HTML</b> message body..."; // Create a vbMAPI wrapper to call the Send method (to avoid prompts) vbMAPI_MailItem SafeItem = vbMAPI_Init.NewOutlookWrapper(Item, false); SafeItem.Send();
Set Session = vbMAPI_Init.NewSession
' This is equivalent to Session.Logon()
Session.MAPIOBJECT = CreateObject("Outlook.Application").GetNamespace("MAPI").MAPIOBJECT
Public Function SendMail(Optional ByVal To_ As String = "", _ Optional ByVal CC As String = "", _ Optional ByVal BCC As String = "", _ Optional ByVal Subject As String = "", _ Optional ByVal MessageBody As String = "", _ Optional ByVal Attachments As String = "") As Boolean On Error GoTo ErrorHandler: Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Dim AttachmentPath As Variant ' Create the vbMAPI Session Set Session = vbMAPI_Init.NewSession ' Logon to the MAPI session Session.LogOn , , True ' Create a new message Set Item = Session.GetDefaultFolder(FolderType_Outbox).Items.Add With Item .Subject = Subject .To_ = To_ .CC = CC .BCC = BCC ' Set the message BODY (HTML or plain text) If Left(MessageBody, 6) = "<HTML>" Then .HTMLBody = MessageBody Else .Body = MessageBody End If ' Add any specified attachments For Each AttachmentPath In Split(Attachments, ";") AttachmentPath = Trim(AttachmentPath) If Len(AttachmentPath) > 0 Then .Attachments.Add AttachmentPath End If Next .Send ' Change to .Display if you want to edit the message in Outlook End With ' Optional - force a send/receive Session.OutlookSendReceiveAll ' If we got here without error, then everything went ok. SendMail = True ExitRoutine: Exit Function ErrorHandler: MsgBox "An error has occurred in SendMail() " & vbCrLf & vbCrLf & _ "Number: " & CStr(Err.Number) & vbCrLf & _ "Description: " & Err.Description, vbApplicationModal Resume ExitRoutine End Function ' Example of usage: SendMail "to_addresses_here", "", "", "My Subject", "My Message Body", "C:\Attach1.jpg; C:\Attach2.jpg"
Public Function SendMail(Optional ByVal To_ As String = "", _ Optional ByVal CC As String = "", _ Optional ByVal BCC As String = "", _ Optional ByVal Subject As String = "", _ Optional ByVal MessageBody As String = "", _ Optional ByVal Attachments As String = "") As Boolean On Error GoTo ErrorHandler Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Dim AttachmentPath As Object ' Create the vbMAPI Session Session = vbMAPI_Init.NewSession ' Logon to the MAPI session Session.LogOn(, , True) ' Create a new message Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add With Item .Subject = Subject .To_ = To_ .CC = CC .BCC = BCC ' Set the message BODY (HTML or plain text) If MessageBody.IndexOf("<HTML>") = 0 Then .HTMLBody.Value = MessageBody Else .Body.Value = MessageBody End If ' Add any specified attachments For Each AttachmentPath In Attachments.Split(";") AttachmentPath = AttachmentPath.Trim() If AttachmentPath.Length() > 0 Then .Attachments.Add(AttachmentPath) End If Next .Send() ' Change to .Display if you want to edit the message in Outlook End With ' Optional - force a send/receive Session.OutlookSendReceiveAll() ' If we got here without error, then everything went ok. SendMail = True ExitRoutine: Exit Function ErrorHandler: MsgBox("An error has occurred in SendMail() " & vbCrLf & vbCrLf & _ "Number: " & CStr(Err.Number) & vbCrLf & _ "Description: " & Err.Description, vbApplicationModal) Resume ExitRoutine End Function ' Example of usage: SendMail("to_addresses_here", "", "", "My Subject", "My Message Body", "C:\Attach1.jpg; C:\Attach2.jpg")
public bool SendMail(string To_, string CC, string BCC, string Subject, string MessageBody, string Attachments) { try { vbMAPI_Session Session; vbMAPI_MailItem Item; string AttachmentPathCopy; // Create the vbMAPI Session Session = vbMAPI_Init.NewSession(); // Logon to the MAPI session Session.LogOn("", "", true, true, 0, false); // Create a new message Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add(null); Item.Subject = Subject; Item.To_ = To_; Item.CC = CC; Item.BCC = BCC; // Set the message BODY (HTML or plain text) if (MessageBody.IndexOf("<HTML>") == 0) { Item.HTMLBody.Value = MessageBody; } else { Item.Body.Value = MessageBody; }; // Add any specified attachments foreach(string AttachmentPath in Attachments.Split(';')) { AttachmentPathCopy = AttachmentPath.Trim(); if (AttachmentPathCopy.Length > 0) { Item.Attachments.Add(AttachmentPathCopy, EnumAttachmentMethod.AttachmentMethod_ByValue, -1, ""); }; }; Item.Send(); // Change to .Display if you want to edit the message in Outlook // Optional - force a send/receive Session.OutlookSendReceiveAll(); // If we got here without error, then everything went ok. return true; } catch { // Error occurred. Do logging/exception handling here. return false; }; } // Example of usage: SendMail("to_addresses_here", "", "", "My Subject", "My Message Body", "C:\Attach1.jpg; C:\Attach2.jpg")
The preferred method for enumerating collections in vbMAPI is to use the For-Each syntax - for example:
Dim Item As vbMAPI_MailItem For Each Item In FolderItems ' Do something with Item Next ' --------------------------------------------- Dim Property As vbMAPI_Property For Each Property In Item.Properties ' Do something with Property Next ' --------------------------------------------- Dim Account As vbMAPI_Account For Each Account In Session.Accounts ' Do something with Account Next
Dim Item As vbMAPI_MailItem For Each Item In FolderItems ' Do something with Item Next ' --------------------------------------------- Dim Property As vbMAPI_Property For Each Property In Item.Properties ' Do something with Property Next ' --------------------------------------------- Dim Account As vbMAPI_Account For Each Account In Session.Accounts ' Do something with Account Next
foreach(vbMAPI_MailItem Item in FolderItems) { // Do something with Item }; // --------------------------------------------- foreach(vbMAPI_Property Property in Item.Properties) { // Do something with Property }; // --------------------------------------------- foreach(vbMAPI_Account Account in Session.Accounts) { // Do something with Account };
This code requires v1.10.1 or later of vbMAPI.
This example shows how to include the default new signature HTML into your HTML e-mails. This routine also embeds local image files, using the new Signature.SetupAttachments functionality.
Public Sub SetHTMLWithSignature(ByVal Item As vbMAPI_MailItem, ByVal HTMLSnippet As String) On Error GoTo NoSignatureOrOtherError Dim FullHTML As String Dim InsertBodyPos As Long Dim Signature As vbMAPI_OutlookSignature Set Signature = Item.Session.OutlookSignatures.DefaultNewSignature FullHTML = Signature.FullHTML Signature.SetupAttachments Item InsertBodyPos = InStr(InStr(1, FullHTML, "<BODY"), FullHTML, ">") Item.HTMLBody = Left(FullHTML, InsertBodyPos) & HTMLSnippet & Right(FullHTML, Len(FullHTML) - InsertBodyPos) Exit Sub NoSignatureOrOtherError: Item.HTMLBody = HTMLSnippet End Sub '------------ ' Usage... '------------ Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Set Session = vbMAPI_Init.NewSession Session.LogOn , , True Set Item = Session.GetDefaultFolder(FolderType_Outbox).Items.Add() Item.Subject = "Test subject..." Item.To_ = "name-or-address" SetHTMLWithSignature Item, "Just a <b>HTML</b> test...<br><br><br>" Item.Send
Public Sub SetHTMLWithSignature(ByVal Item As vbMAPI_MailItem, ByVal HTMLSnippet As String) Try Dim FullHTML As String Dim FullHTML_UpperCase As String Dim InsertBodyPos As Long Dim Signature As vbMAPI_OutlookSignature Signature = Item.Session.OutlookSignatures.DefaultNewSignature FullHTML = Signature.FullHTML FullHTML_UpperCase = FullHTML.ToUpper() Signature.SetupAttachments Item InsertBodyPos = FullHTML_UpperCase.IndexOf(">", FullHTML_UpperCase.IndexOf("<BODY")) Item.HTMLBody.Value = FullHTML.Substring(0, InsertBodyPos + 1) & HTMLSnippet & _ FullHTML.Substring(InsertBodyPos + 1) Catch ex As Exception Item.HTMLBody.Value = HTMLSnippet End Try End Sub '------------ ' Usage... '------------ Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Session = vbMAPI_Init.NewSession Session.LogOn(, , True) Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add() Item.Subject = "Test subject..." Item.To_ = "name-or-address" SetHTMLWithSignature Item, "Just a <b>HTML</b> test...<br><br><br>" Item.Send()
public void SetHTMLWithSignature(vbMAPI_MailItem Item, string HTMLSnippet) { try { string FullHTML; string FullHTML_UpperCase; int InsertBodyPos; vbMAPI_OutlookSignature Signature; Signature = Item.Session.OutlookSignatures.DefaultNewSignature; FullHTML = Signature.FullHTML; FullHTML_UpperCase = FullHTML.ToUpper(); Signature.SetupAttachments(Item); InsertBodyPos = FullHTML_UpperCase.IndexOf(">", FullHTML_UpperCase.IndexOf("<BODY")); Item.HTMLBody.Value = FullHTML.Substring(0, InsertBodyPos + 1) + HTMLSnippet + FullHTML.Substring(InsertBodyPos + 1); } catch { Item.HTMLBody.Value = HTMLSnippet; }; } '------------ ' Usage... '------------ vbMAPI_Session Session; vbMAPI_MailItem Item; Session = vbMAPI_Init.NewSession(); Session.LogOn("", "", true, true, 0, false); Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add(); Item.Subject = "Test subject..."; Item.To_ = "name-or-address"; SetHTMLWithSignature(Item, "Just a <b>HTML</b> test...<br><br><br>"); Item.Send();
First, we can enumerate through the Outlook accounts by using the Accounts property of vbMAPI_Session. This returns an object of type vbMAPI_Accounts, which is enumerable using the standard For-Each syntax:
Dim Account As vbMAPI_Account For Each Account In Session.Accounts MsgBox Account.AccountTypeAsStr & ": " & Account.Name Next
Dim Account As vbMAPI_Account For Each Account In Session.Accounts MsgBox Account.AccountTypeAsStr & ": " & Account.Name Next
foreach(vbMAPI_Account Account in Session.Accounts) { MessageBox.Show(Account.AccountTypeAsStr + ": " + Account.Name); };
For instance, on my machine this lists my two accounts of "Wayne Phillips EXCHANGE" and "Wayne Phillips GMAIL".
If you want to specify that an e-mail gets sent using a specific account (rather than the default account), you can do this by simply setting the vbMAPI_MailItem SendAccountName property to the string name of the account, and vbMAPI will do the rest:
Dim Item As vbMAPI_MailItem ' Create the e-mail here (left for you to fill in) ' Before sending, set the SendAccountName property: Item.SendAccountName = "Wayne Phillips GMAIL" Item.Send
Dim Item As vbMAPI_MailItem ' Create the e-mail here (left for you to fill in) ' Before sending, set the SendAccountName property: Item.SendAccountName = "Wayne Phillips GMAIL" Item.Send
vbMAPI_MailItem Item; // Create the e-mail here (left for you to fill in) // Before sending, set the SendAccountName property: Item.SendAccountName = "Wayne Phillips GMAIL"; Item.Send();
Many vbMAPI objects such as vbMAPI_Store, vbMAPI_Folder and vbMAPI_MailItem all expose a member called Properties. This member returns an object of type vbMAPI_Properties. The vbMAPI_Properties class gives you access to the low-level MAPI properties on objects. This is the equivalent of the Fields collection in Outlook Redemption.
Using the vbMAPI_Properties class, we can very easily enumerate through all the MAPI properties that are set on an object:
Dim Property As vbMAPI_Property For Each Property In Item.Properties Debug.Print Property.PropTagSymbol & ": " & Property.Value Next
Dim Property As vbMAPI_Property For Each Property In Item.Properties Debug.Print Property.PropTagSymbol & ": " & Property.Value Next
foreach(vbMAPI_Property Property in Item.Properties) { Debug.Print(Property.PropTagSymbol + ": " + Property.Value); };
We can also change the value of low-level MAPI properties by again using the vbMAPI_Properties class:
In order to send reports from Microsoft Access as attachments in your e-mails, we first have to output the report to a temporary file and then add the file as an attachment to your MailItem.
Dim strTempPath As String strTempPath = Environ("Temp") & "\" & "Report.rtf" DoCmd.OutputTo acOutputReport, "Your_Report_Name", acFormatRTF, strTempPath Item.Attachments.Add strTempPath
' This code requires type library reference to Access etc
Dim strTempPath As String
strTempPath = System.Environment.GetEnvironmentVariable("Temp") & "\" & "Report.rtf"
objAccessApp.DoCmd.OutputTo(Access.acOutputReport, "Your_Report_Name", Access.acFormatRTF, strTempPath)
Item.Attachments.Add(strTempPath)
// This code requires type library reference to Access etc
string strTempPath;
strTempPath = System.Environment.GetEnvironmentVariable("Temp") + "\" + "Report.rtf";
objAccessApp.DoCmd.OutputTo(Access.acOutputReport, "Your_Report_Name", Access.acFormatRTF, strTempPath);
Item.Attachments.Add(strTempPath);
MAPI expects all recipients to be "resolved" before sending a message. By default, vbMAPI (like Outlook and Outlook Redemption) will automatically resolve recipients when you call the Send method of a MailItem.
By "Resolve" MAPI means that either the supplied recipient display name is resolved to your address book, or a one-off identifier has been created for the SMTP e-mail address recipient.
But, if you are writing an automated script, let's say for a website newsletter, you might not want MAPI to resolve names to your address book. For example, all of your addresses might be valid SMTP e-mail addresses, so there is no point in MAPI trying to resolve to your address book in this case.
In fact, resolving to your address book will likely be much slower, and should be avoided if not needed.
Option 1. Resolving manually
One option is to resolve recipients manually before calling the Send method. By default, the Send method does this before sending:
For Each Recipient In Item.Recipients Recipient.Resolve Next
For Each Recipient In Item.Recipients Recipient.Resolve Next
foreach(vbMAPI_Recipient Recipient in Item.Recipients) { Recipient.Resolve(true, 0); };
But if we are expecting all of our recipients to be SMTP email addresses, then we can optimize it by using:
For Each Recipient In Item.Recipients Recipient.ResolveOneOff Next
For Each Recipient In Item.Recipients Recipient.ResolveOneOff Next
foreach(vbMAPI_Recipient Recipient in Item.Recipients) { Recipient.ResolveOneOff(); };
The ResolveOneOff method does not resolve addresses to your address book, and is the preferred method in such cases.
Option 2. Use Options.AutoResolveMode
Alternatively, if you don't want to resolve the recipients manually, you can change the default behaviour of the Send method like so:
Item.Session.Options.AutoResolveMode = AutoResolve_OneOff
Item.Session.Options.AutoResolveMode = EnumAutoResolveMode.AutoResolve_OneOff
Item.Session.Options.AutoResolveMode = EnumAutoResolveMode.AutoResolve_OneOff;
To embed images into an e-mail, you need to add the image files as attachments to your message, tagging them with a unique ContentID value, and then you can refer to the images in your HTML body using the a prefix of "cid:" before the tag. The ContentID value that you choose has to be unique (to all attachments in the message), but can be any string value.
For example:
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Dim Attach As vbMAPI_Attachment Set Session = vbMAPI_Init.NewSession Session.LogOn , , True Set Item = Session.GetDefaultFolder(FolderType_Outbox).Items.Add() Item.HTMLBody = "<img src=""cid:MyImageID1"">" Set Attach = Item.Attachments.Add("C:\EverythingAccessLogo.jpg") Attach.ContentID = "MyImageID1" Attach.Hidden = True Item.HidePaperClip = True Item.Subject = "My embedded image test..." Item.Save
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Dim Attach As vbMAPI_Attachment Session = vbMAPI_Init.NewSession Session.LogOn(, , True) Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add() Item.HTMLBody.Value = "<img src=""cid:MyImageID1"">" Attach = Item.Attachments.Add("C:\EverythingAccessLogo.jpg") Attach.ContentID = "MyImageID1" Attach.Hidden = True Item.HidePaperClip = True Item.Subject = "My embedded image test..." Item.Save()
vbMAPI_Session Session; vbMAPI_MailItem Item; vbMAPI_Attachment Attach; Session = vbMAPI_Init.NewSession(); Session.LogOn("","",true,true,0,false); Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox).Items.Add(null); Item.HTMLBody.Value = "<img src=""cid:MyImageID1"">"; Attach = Item.Attachments.Add("C:\EverythingAccessLogo.jpg", EnumAttachmentMethod.AttachmentMethod_ByValue, -1, ""); Attach.ContentID = "MyImageID1"; Attach.Hidden = true; Item.HidePaperClip = true; Item.Subject = "My embedded image test..."; Item.Save();
Item.ReadReceiptEntryID = Session.AddressBook.ResolveName("address-or-user-here").EntryID Item.ReadReceiptRequested = True
Item.ReadReceiptEntryID = Session.AddressBook.ResolveName("address-or-user-here").EntryID Item.ReadReceiptRequested = True
Item.ReadReceiptEntryID = Session.AddressBook.ResolveName("address-or-user-here", true, 0).EntryID; Item.ReadReceiptRequested = true;
With Session.AddressBook.ResolveName("address-or-user-here") Item.SenderName = .Name Item.SenderEntryID = .EntryID Item.SenderSearchKey = .SearchKey Item.SentOnBehalfOfName = .Name Item.SentOnBehalfOfEntryID = .EntryID Item.SentOnBehalfOfAddressType = .AddressType Item.SentOnBehalfOfEmailAddress = .Address Item.SentOnBehalfOfSearchKey = .SearchKey End With
With Session.AddressBook.ResolveName("address-or-user-here") Item.SenderName = .Name Item.SenderEntryID = .EntryID Item.SenderSearchKey = .SearchKey Item.SentOnBehalfOfName = .Name Item.SentOnBehalfOfEntryID = .EntryID Item.SentOnBehalfOfAddressType = .AddressType Item.SentOnBehalfOfEmailAddress = .Address Item.SentOnBehalfOfSearchKey = .SearchKey End With
vbMAPI_AddressEntry AddressEntry = Session.AddressBook.ResolveName("address-or-user-here", true, 0); Item.SenderName = AddressEntry.Name; Item.SenderEntryID = AddressEntry.EntryID; Item.SenderSearchKey = AddressEntry.SearchKey; Item.SentOnBehalfOfName = AddressEntry.Name; Item.SentOnBehalfOfEntryID = AddressEntry.EntryID; Item.SentOnBehalfOfAddressType = AddressEntry.AddressType; Item.SentOnBehalfOfEmailAddress = AddressEntry.Address; Item.SentOnBehalfOfSearchKey = AddressEntry.SearchKey;
This technique is best suited for sending an e-mail as if from another Exchange user. Many POP3/SMTP e-mail service providers will not allow you to mask the From address in this manner, therefore you should try to avoid this and instead set up a proper Outlook account for the from e-mail address and specify that account as the send-account when sending the e-mail.
' ------------------------------------------------------------------------------------ ' Validates each recipient name/address, prompting the user to correct illegal entries ' Returns a string identifying unresolvable recipients ' ------------------------------------------------------------------------------------ Public Function ValidateRecipients(Item As vbMAPI_MailItem) As String Dim Recipient As vbMAPI_Recipient Dim UnresolvedAddresses As String For Each Recipient In Item.Recipients ' Calling Recipient.Resolve will cause Outlook to prompt the user to correct ' or disambiguate the entered address (or name) if it is invalid or unrecognized If Not Recipient.Resolve Then ' Outlook could not resolve the address automatically and the ' user cancelled the dialog prompt requesting corrections If Len(UnresolvedAddresses) > 0 Then UnresolvedAddresses = UnresolvedAddresses & "; " UnresolvedAddresses = UnresolvedAddresses & Recipient.Name End If Next ValidateRecipients = UnresolvedAddresses End Function
' ------------------------------------------------------------------------------------ ' Validates each recipient name/address, prompting the user to correct illegal entries ' Returns a string identifying unresolvable recipients ' ------------------------------------------------------------------------------------ Public Function ValidateRecipients(Item As vbMAPI_MailItem) As String Dim Recipient As vbMAPI_Recipient Dim UnresolvedAddresses As String For Each Recipient In Item.Recipients ' Calling Recipient.Resolve will cause Outlook to prompt the user to correct ' or disambiguate the entered address (or name) if it is invalid or unrecognized If Not Recipient.Resolve Then ' Outlook could not resolve the address automatically and the ' user cancelled the dialog prompt requesting corrections If UnresolvedAddresses.Length > 0 Then UnresolvedAddresses = UnresolvedAddresses & "; " UnresolvedAddresses = UnresolvedAddresses & Recipient.Name End If Next ValidateRecipients = UnresolvedAddresses End Function
// ------------------------------------------------------------------------------------ // Validates each recipient name/address, prompting the user to correct illegal entries // Returns a string identifying unresolvable recipients // ------------------------------------------------------------------------------------ public string ValidateRecipients(vbMAPI_MailItem Item) { string UnresolvedAddresses = ""; foreach(vbMAPI_Recipient Recipient in Item.Recipients) { // Calling Recipient.Resolve will cause Outlook to prompt the user to correct // or disambiguate the entered address (or name) if it is invalid or unrecognized if (Recipient.Resolve(true, 0) == false) { // Outlook could not resolve the address automatically and the // user cancelled the dialog prompt requesting corrections if (UnresolvedAddresses.Length > 0) { UnresolvedAddresses = UnresolvedAddresses + "; "; }; UnresolvedAddresses = UnresolvedAddresses + Recipient.Name; }; }; return UnresolvedAddresses; }
vbMAPI doesn't directly support CreateItemFromTemplate, but the functionality can easily be reproduced:
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Set Session = vbMAPI_Init.NewSession Session.LogOn , , True Set Item = Session.GetMessageFromMsgFile(strOFTPath) Set Item = Item.Copy(Session.GetDefaultFolder(FolderType_Outbox))
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Set Session = vbMAPI_Init.NewSession Session.LogOn(, , True) Set Item = Session.GetMessageFromMsgFile(strOFTPath) Set Item = Item.Copy(Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox))
vbMAPI_Session Session; vbMAPI_MailItem Item; Session = vbMAPI_Init.NewSession(); Session.LogOn("", "", true, true, 0, false); Item = Session.GetMessageFromMsgFile(strOFTPath, false); Item = Item.Copy(Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Outbox), true);
This works because an OFT template file is essentially just a MSG format file.
vbMAPI doesn't natively support this in the Object Model at the moment, but we are working on getting this functionality added to the next release.
Public Function ToHex(ByVal LongVal As Long) As String ToHex = Hex(LongVal) While Len(ToHex) < 8 ToHex = "0" & ToHex Wend ToHex = Right(ToHex, 2) & _ Mid(ToHex, 5, 2) & _ Mid(ToHex, 3, 2) & _ Left(ToHex, 2) End Function Public Function GetSingleFlatEntryList(EntryID As String) As String GetSingleFlatEntryList = ToHex(1) & ToHex((Len(EntryID) / 2) + 4) & ToHex(Len(EntryID) / 2) & EntryID End Function
Then, you call GetSingleFlatEntryList like this:
With Session.AddressBook.ResolveName("address-or-user-here") Item.Properties(PR_REPLY_RECIPIENT_ENTRIES + 1) = GetSingleFlatEntryList(.EntryID) Item.Properties(PR_REPLY_RECIPIENT_NAMES) = .Name End With
Dim Session As vbMAPI_Session Dim Item As vbMAPI_AppointmentItem Set Session = vbMAPI_Init.NewSession Session.LogOn , , True Set Item = Session.GetDefaultFolder(FolderType_Calendar).Items.Add Item.Subject = "An appointment!" Item.Start = Now() + 7 ' set start time 7 days in future Item.End_ = DateAdd("n", 30, Item.Start) ' Duration: 30 minutes Item.Recipients.Add "email-address-here" ' Add a recipient Item.IsRecurring = False Item.Location = "Meeting room 123" Item.Send
Dim Session As vbMAPI_Session Dim Item As vbMAPI_AppointmentItem Session = vbMAPI_Init.NewSession Session.LogOn(, , True) Item = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Calendar).Items.Add() Item.Subject = "An appointment!" Item.Start = Now().AddDays(7) ' set start time 7 days in future Item.End_ = Item.Start.AddMinutes(30) ' Duration 30 minutes Item.IsRecurring = False Item.Location = "Meeting room 123" Item.Recipients.Add("email-address-here") ' Add a recipient Item.Send()
vbMAPI_Session Session; vbMAPI_AppointmentItem Item; Session = vbMAPI_Init.NewSession(); Session.LogOn("", "", true, true, 0, false); Item = (vbMAPI_AppointmentItem)Session.GetDefaultFolder( EnumDefaultFolderType.FolderType_Calendar).Items.Add(); Item.Subject = "An appointment!"; Item.Start = DateTime.Now.AddDays(7); // set start time 7 days in future Item.End_ = Item.Start.AddMinutes(30); ' Duration 30 minutes Item.IsRecurring = false; Item.Location = "Meeting room 123"; Item.Recipients.Add("email-address-here", EnumRecipientType.Recipient_TO); ' Add a recipient Item.Send();
Before sending the item, simply set the DeleteAfterSubmit property to True:
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Set Session = vbMAPI_Init.NewSession Session.LogOn , , True For Each Item In Session.GetDefaultFolder(FolderType_Inbox).Items Debug.Print Item.Subject Next
Dim Session As vbMAPI_Session Dim Item As vbMAPI_MailItem Session = vbMAPI_Init.NewSession Session.LogOn(, , True) For Each Item In Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Inbox).Items Debug.Print(Item.Subject) Next
vbMAPI_Session Session; Session = vbMAPI_Init.NewSession(); Session.LogOn("", "", true, true, 0, false); vbMAPI_Folder Folder = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Inbox); foreach(vbMAPI_MailItem Item in Folder.Items) { System.Diagnostics.Debug.Print(Item.Subject); };
To work with the vbMAPI_ContactItem class, we can simply cast any vbMAPI_MailItem directly to a variable of that type (this also works for vbMAPI_AppointmentItem etc).
For example, the vbMAPI_FolderItems collection returns generic objects of type vbMAPI_MailItem, but you can simply declare your Item variable as vbMAPI_ContactItem instead:
Dim Session As vbMAPI_Session Dim Item As vbMAPI_ContactItem Set Session = vbMAPI_Init.NewSession Session.LogOn , , True For Each Item In Session.GetDefaultFolder(FolderType_Contacts).Items Debug.Print Item.FullName Next
Dim Session As vbMAPI_Session Dim Item As vbMAPI_ContactItem Session = vbMAPI_Init.NewSession Session.LogOn(, , True) For Each Item In Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Contacts).Items Debug.Print(Item.FullName) Next
vbMAPI_Session Session; Session = vbMAPI_Init.NewSession(); Session.LogOn("", "", true, true, 0, false); vbMAPI_Folder Folder = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Contacts); foreach(vbMAPI_ContactItem Item in Folder.Items) { System.Diagnostics.Debug.Print(Item.FullName); };
Please note: There is a small breaking change in v1.11.0 of vbMAPI affecting only VBA developers:
Due to new optimizations in the latest VBA7 64-bit compiler (available in Office 2010 SP1), we had to make some changes to our Virtual-COM engine to make it compatible.
The changes made to our engine have very little impact to VBA developers, but there is one specific case that needs highlighting.
Implicit casting from objects declared as vbMAPI_MailItem to other compatible item classes (like vbMAPI_AppointmentItem) and vice-versa is no longer supported in the VBA edition of vbMAPI.
To limit the need to change existing code as much as possible, all properties and methods that used to return an explicit vbMAPI_MailItem object, will now return a generic Object instead which can then be cast to any of the allowed types (vbMAPI_MailItem, vbMAPI_AppointmentItem, vbMAPI_ContactItem).
The following new object methods have been provided to cast explicitly between compatible types:
vbMAPI_MailItem.CastToAppointmentItem
vbMAPI_MailItem.CastToContactItem
vbMAPI_AppointmentItem.CastToMailItem
vbMAPI_AppointmentItem.CastToContactItem
vbMAPI_ContactItem.CastToMailItem
vbMAPI_ContactItem.CastToAppointmentItem
In short, if you had code like this in VBA:
Set AppointmentItem = MailItem
You will now need to use an explicit cast instead, by using the new properties provided:
Set AppointmentItem = MailItem.CastToAppointmentItem
This change does not affect .NET languages.
Item.Attachments.AddBlank("MyFile.txt").DataAsText = "This is just an example..."
Item.Attachments.AddBlank("MyFile.txt").DataAsText = "This is just an example..."
Item.Attachments.AddBlank("MyFile.txt", -1, "").DataAsText = "This is just an example...";
If you're writing an Outook addin and want vbMAPI to share the existing MAPI session that Outlook has already logged onto, you can set the MAPIOBJECT property directly to the object returned by the Outlook Namespace MAPIOBJECT property.
' Retrieve the MAPI namespace from the instance of Outlook.Application Set OutlookNamespace = OutlookObj.GetNamespace("MAPI") ' Create a new vbMAPI_Session object Dim Session As vbMAPI_Session Set Session = vbMAPI_Init.NewSession ' Instead of calling Logon(), attach to the existing Outlook MAPI session object Session.MAPIOBJECT = OutlookNamespace.MAPIOBJECT ' The vbMAPI Session is now logged on to the same MAPI session as your Outlook instance
' Retrieve the MAPI namespace from the instance of Outlook.Application OutlookNamespace = OutlookObj.GetNamespace("MAPI") ' Create a new vbMAPI_Session object Dim Session As vbMAPI_Session Session = vbMAPI_Init.NewSession ' Instead of calling Logon(), attach to the existing Outlook MAPI session object Session.MAPIOBJECT = OutlookNamespace.MAPIOBJECT ' The vbMAPI Session is now logged on to the same MAPI session as your Outlook instance
// Retrieve the MAPI namespace from the instance of Outlook.Application OutlookNamespace = OutlookObj.GetNamespace("MAPI"); // Create a new vbMAPI_Session object vbMAPI_Session Session; Session = vbMAPI_Init.NewSession(); // Instead of calling Logon(), attach to the existing Outlook MAPI session object Session.MAPIOBJECT = OutlookNamespace.MAPIOBJECT; // The vbMAPI Session is now logged on to the same MAPI session as your Outlook instance
' To obtain an object referring to a subfolder of one of the default folders, use this syntax: Dim Folder As vbMAPI_Folder Set Folder = Session.GetDefaultFolder(FolderType_Inbox).Folders("FolderName") ' To obtain an object referring to a subfolder of the main mailbox (the IPM root folder): Dim Folder As vbMAPI_Folder Set Folder = Session.Stores.DefaultStore.IPMRootFolder.Folders("FolderName")
' To obtain an object referring to a subfolder of one of the default folders, use this syntax: Dim Folder As vbMAPI_Folder Folder = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Inbox).Folders("FolderName") ' To obtain an object referring to a subfolder of the main mailbox (the IPM root folder): Dim Folder As vbMAPI_Folder Folder = Session.Stores.DefaultStore.IPMRootFolder.Folders("FolderName")
// To obtain an object referring to a subfolder of one of the default folders, use this syntax: vbMAPI_Folder Folder; Folder = Session.GetDefaultFolder(EnumDefaultFolderType.FolderType_Inbox).Folders.Item("FolderName"); // To obtain an object referring to a subfolder of the main mailbox (the IPM root folder): vbMAPI_Folder Folder; Folder = Session.Stores.DefaultStore.IPMRootFolder.Folders.Item("FolderName");
iTech Masters | VAT: GB202994606 | Terms | Sitemap | Newsletter