Code Examples

Foreword

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.

Wrapping an Outlook MailItem

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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();

Working with Click-To-Run environments

When working with marshalled Click-To-Run (C2R) environments (e.g. from Access 2010 to Outlook 2016), you may find that your code using vbMAPI freezes, or crashes at certain points. These are caused by known problems with the MAPI subsystem interacting with C2R environments (particularly affecting Outlook 2016).

The most reliable workaround is to use an IMAPISession obtained from a COM-marshalled instance of Outlook. To do this with vbMAPI, instead of calling Session.LogOn(), we set the MAPIOBJECT property like this:
Set Session = vbMAPI_Init.NewSession

' This is equivalent to Session.Logon()
Session.MAPIOBJECT = CreateObject("Outlook.Application").GetNamespace("MAPI").MAPIOBJECT

The above VBA example will assign a valid IMAPISession object to your vbMAPI_Session object. This is equivalent to a normal vbMAPI_Session::LogOn call to the default profile. This is our recommended workaround for these MAPI bugs when working with Outlook 2013/2016 C2R.

Please note that when using this approach with Outlook 2013 C2R, you may need to apply this registry patch on the users machine (not needed for Outlook 2016).

A simple SendMail function

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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")




Collections in vbMAPI

The preferred method for enumerating collections in vbMAPI is to use the For-Each syntax - for example:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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
};

Sending an HTML e-mail including the users default Outlook signature

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.

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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();


Sending mail through a specific Outlook Account [Outlook 2003+]

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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();

Accessing low-level MAPI properties

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
Item.Properties(PR_SUBJECT) = "Some subject..."
Item.Save
Item.Properties(PR_SUBJECT).Value = "Some subject..."
Item.Save
Item.Properties(PR_SUBJECT).Value = "Some subject...";
Item.Save();

Sending reports from Microsoft Access

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.

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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);

Resolving Recipients

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
Item.Session.Options.AutoResolveMode = AutoResolve_OneOff
Item.Session.Options.AutoResolveMode = EnumAutoResolveMode.AutoResolve_OneOff
Item.Session.Options.AutoResolveMode = EnumAutoResolveMode.AutoResolve_OneOff;

Embedding images into e-mails

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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();

Changing the address where delivery receipts get sent

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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;

Changing the From address of an e-mail

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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.

Validating recipients manually

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
' ------------------------------------------------------------------------------------
' 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;
}

Equivalent to CreateItemFromTemplate()

vbMAPI doesn't directly support CreateItemFromTemplate, but the functionality can easily be reproduced:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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.

Setting the Reply address when sending an e-mail

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

Sending an appointment request

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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();

Prevent sent e-mails being stored in the SentItems Folder

Before sending the item, simply set the DeleteAfterSubmit property to True:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
Item.DeleteAfterSubmit = True
Item.Send
Item.DeleteAfterSubmit = True
Item.Send
Item.DeleteAfterSubmit = true;
Item.Send();

Iterate through all messages in the Inbox

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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);
};

Iterate through all contacts in the Outlook contacts folder

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:

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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.

Adding a text attachment directly from a string

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
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...";

Sharing an existing Outlook MAPI session

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.

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
' 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

Working with subfolders

 Code language:   VBA / VB6    VB.NET    C#            (changing code language requires javascript to be enabled)
' 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");