Solved

Sending Email using MAPI33

Posted on 2004-09-30
6
2,965 Views
Last Modified: 2010-08-05
I am trying to use MAPI33 to send an email over a MAPI profile without triggering the security prompt.  Outlook Redemption does this to a limited extent but requires office and isn't as powerful.  
I will award 500 points to the first person to come up with complete working C# code that accomplishes this task using the MAPI33 library.

The function needs to be able to take the standard message fields such as To, CC, BCC, Subject, Body, and some form of attachments.  
If its any help, I am working with the source code sample provided at http://g8.cx/mapi so if you need to take advantage of any functions in the MapiWrapper.cs file, you can.
0
Comment
Question by:masoncooper
6 Comments
 
LVL 1

Accepted Solution

by:
muellerfan earned 500 total points
ID: 12191796
This is my sendemail function.  I don't have attachments and my body assumes html, but it should get you going.  Isn't ExMAPI and OOM fun :)

enum oneoff{_DISPLAY_NAME, _ADDRTYPE, _EMAIL_ADDRESS, _RECIPIENT_TYPE, NUM_RECIP_PROPS};
public void SendEmail(string from, string to, string subject, string body, ref Microsoft.Office.Interop.Outlook.Application appobj)
            {
                  Error hr;
                  IMAPISession session;
                  MAPI33.MAPI.TYPE objtype;
                  MAPI33.IUnknown unk;
                  IMAPITable tblMsgStores;
                  ENTRYID storeeid = null;
                  Tags [] itags;
                  IMsgStore store;
                  ENTRYID outboxid = null;
                  IMAPIFolder outbox;
                  IAddrBook ab;
                  MAPI33.SPropProblem [] probs;
                  
                  //OPEN MAPI33.MAPI
                  hr = MAPI33.MAPI.Initialize(null);
                  hr = MAPI33.MAPI.LogonEx(IntPtr.Zero, null, null,   MAPI33.MAPI.FLAGS.Extended |MAPI33.MAPI.FLAGS.LogonUI |MAPI33.MAPI.FLAGS.NoMail,      out session);
                  
                  //FIND THE DEFAULT STORE
                  hr = session.GetMsgStoresTable(0, out tblMsgStores);
                  
                  MAPI33.MapiTypes.Value[,] rows;
                  itags = new Tags[] {Tags.PR_ENTRYID, Tags.PR_DEFAULT_STORE};
                  tblMsgStores.SetColumns(itags, IMAPITable.FLAGS.Default);
                  hr = tblMsgStores.QueryRows(50, 0, out rows);
                  tblMsgStores.Dispose();

                  for (int i=0; i <= rows.GetUpperBound(0); i++)
                  {
                        bool isdefault = ((MAPI33.MapiTypes.MapiBoolean)rows[i,1]).Value;
                        if (isdefault)
                        {      
                              storeeid = new ENTRYID((byte[])((MapiBinary)rows[i,0]).Value);
                              break;
                        }
                  }

                  // NOW WE CAN OPEN OUR MESSAGE STORE
                  //hr = session.OpenMsgStore(IntPtr.Zero, storeeid, Guid.Empty,IMAPISession.FLAGS.Modify, out store);
                  hr = session.OpenEntry(storeeid, Guid.Empty, IMAPISession.FLAGS.Modify, out objtype, out unk);
                  store = (IMsgStore)unk;
                  unk.Dispose();

                  //GET THE OUTBOX FOLDER
                  itags = new Tags[] {Tags.PR_IPM_OUTBOX_ENTRYID};
                  MAPI33.MapiTypes.Value[] pvals = new MAPI33.MapiTypes.Value[0];
                  hr = store.GetProps(itags, 0, out pvals);
                  for (int k=0; k < pvals.Length; k++)
                        outboxid = new ENTRYID((byte[])((MapiBinary)pvals[k]).Value);
                  
                  hr = store.OpenEntry(outboxid, Guid.Empty, IMsgStore.FLAGS.Modify, out objtype, out unk);
                  outbox = (IMAPIFolder)unk;
                  unk.Dispose();

                  //CREATE THE NEW MESSAGE
                  IMessage message;
                  hr = outbox.CreateMessage(Guid.Empty, 0, out message);
                  hr = session.OpenAddressBook(IntPtr.Zero, Guid.Empty, 0, out ab);

                  //ADD RECIPIENTS
                  MAPI33.ADRENTRY [] sendto = new ADRENTRY[1];
                  sendto[0] = new ADRENTRY((int)oneoff.NUM_RECIP_PROPS);
                  sendto[0].PropVals[0] = new MapiString(Tags.PR_DISPLAY_NAME, to);
                  sendto[0].PropVals[(int)oneoff._ADDRTYPE] = new MapiString(Tags.PR_ADDRTYPE, "SMTP");
                  sendto[0].PropVals[(int)oneoff._EMAIL_ADDRESS] = new MapiString(Tags.PR_EMAIL_ADDRESS, to);
                  sendto[0].PropVals[(int)oneoff._RECIPIENT_TYPE] = new MAPI33.MapiTypes.MapiInt32(Tags.PR_RECIPIENT_TYPE,1);
                        
                  hr = ab.ResolveName(IntPtr.Zero, 0, null, ref sendto);
                  
                  //IF RECIPIENT IS NOT FOUND, WE CREATE A ONE-OFF
                  if (hr == MAPI33.Error.NotFound)
                  {
                        ENTRYID oneoffentry;
                        
                        hr = ab.CreateOneOff(to, "SMTP", to, 0, out oneoffentry);
                        
                        sendto[0] = new ADRENTRY((int)oneoff.NUM_RECIP_PROPS + 1);
                        sendto[0].PropVals[(int)oneoff._DISPLAY_NAME] = new MapiString(Tags.PR_DISPLAY_NAME, to);
                        sendto[0].PropVals[(int)oneoff._ADDRTYPE] = new MapiString(Tags.PR_ADDRTYPE, "SMTP");
                        sendto[0].PropVals[(int)oneoff._EMAIL_ADDRESS] = new MapiString(Tags.PR_EMAIL_ADDRESS, to);
                        sendto[0].PropVals[(int)oneoff._RECIPIENT_TYPE] = new MAPI33.MapiTypes.MapiInt32(Tags.PR_RECIPIENT_TYPE,1);
                        sendto[0].PropVals[(int)oneoff.NUM_RECIP_PROPS] = new MAPI33.MapiTypes.MapiBinary(Tags.PR_ENTRYID, oneoffentry.ab);
                  }
                  
                  hr = message.ModifyRecipients(IMessage.FLAGS.ModrecipAdd, sendto);
                  
                  //ADD SUBJECT
                  MAPI33.MapiTypes.Value[] props = new MAPI33.MapiTypes.Value[1];
                  props[0] = new MapiString(Tags.PR_SUBJECT, subject);
                  hr = message.SetProps(props, out probs);
                  
                  //ADD BODY
                  body = body.Replace("\n", "<br>");
                  props = new MAPI33.MapiTypes.Value[1];
                  props[0] = new MapiString(Tags.PR_BODY_HTML, body);
                  hr = message.SetProps(props, out probs);
                  
                  //SET FLAGS
                  props = new MAPI33.MapiTypes.Value[1];
                  props[0] =  new MapiBoolean(Tags.PR_DELETE_AFTER_SUBMIT, true);
                  hr = message.SetProps(props, out probs);


                  //SEND MESSAGE
                  hr = message.SubmitMessage(0);
                  
                  ab.Dispose();
                  message.Dispose();
                  outbox.Dispose();
                  store.Dispose();

                  message = null;

 
                  session.Logoff(IntPtr.Zero, 0);
                  session.Dispose();
                  MAPI33.MAPI.Uninitialize();
                  
            }
0
 
LVL 1

Expert Comment

by:muellerfan
ID: 12191844
BTW, don't know if you've seen this link.  It's obviously not MAPI33, but it helped me get as far as I did:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mapi/html/_mapi1book_handling_an_outgoing_message.asp
0
 
LVL 2

Author Comment

by:masoncooper
ID: 12192090
Great code muellerfan. I noticed you pass an outlook interop app object as an argument but  appobj isn't being used.  I guess this is something related to another bit of code of yours?  I was able to remove that argument and the code worked just fine.

Thanks for your help, A+ Response!
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Expert Comment

by:muellerfan
ID: 12192797
Thank you!  It was a challenge.  You are right about appobj being related to another bit of code that I'm actually not even using anymore.  I guess I can get rid of that argument.
Thanks!
Christie
0
 

Expert Comment

by:grace627
ID: 13808437

Hi Do you know what happened? When i am using above code?
Thanks!

An unhandled exception of type 'System.MissingMethodException' occurred in finaltest.exe

Additional information: Method not found: MAPI33.Error __MAPI33__INTERNALS__.MAPITable.QueryRows(Int32, FLAGS, MAPI33.MapiTypes.Value[,] ByRef).
0
 

Expert Comment

by:Yousefi
ID: 27724432
Hi,

How do I get the current user SMTP address in outlook 2003. See the code below but I get the erorr InvaliEntyId.

Thanks,
Dave

            MAPI33.IMAPISession session;
            Error hr;
            MAPIINIT init = new MAPIINIT();
            init.Flags = MAPIINIT.FLAGS.NoCoInit | MAPIINIT.FLAGS.MultithreadNotifications | MAPIINIT.FLAGS.NTService;
            //OPEN MAPI33.MAPI
            hr = MAPI33.MAPI.Initialize(init);

                hr = MAPI33.MAPI.LogonEx(IntPtr.Zero, null,
                      null, MAPI33.MAPI.FLAGS.Extended | MAPI33.MAPI.FLAGS.LogonUI | MAPI33.MAPI.FLAGS.NoMail,
                      out session);
                if (hr == 0)
                {
                    MessageBox.Show("Logon Successful");
                    getcurrentuser(ref session);
                   
                }
                else
                {
                    MessageBox.Show("Logon Failed " + hr.ToString());
                }
                session.Logoff(IntPtr.Zero, 0);
                session.Dispose();
                MAPI33.MAPI.Uninitialize();


 private void getcurrentuser(ref MAPI33.IMAPISession session)
        {
            Error hr;
            MAPI33.ENTRYID entry;
            MAPI33.IAddrBook ab;
            MAPI33.IUnknown unknown = null;
            MAPI33.MAPI.TYPE retType;
            string myaddress, myname;

            myaddress = myname = "";

            hr = session.QueryIdentity(out entry);
            hr = session.OpenAddressBook(IntPtr.Zero, Guid.Empty, 0, out ab);
            hr = ab.OpenEntry(entry, Guid.Empty, 0, out retType, out unknown);

            /* THIS IS A HACK.  SOMETIMES ON OUTLOOK 2003, QUERYIDENTITY
                DOESN'T WORK  THE FIRST TIME, BUT WILL ON THE 2ND OR 3RD TRY */
            int count = 0;
            while (hr != MAPI33.Error.Success && count < 10)
            {
                hr = session.QueryIdentity(out entry);
                hr = ab.OpenEntry(entry, Guid.Empty, 0, out retType, out unknown);
                count++;
            }

            if (hr != MAPI33.Error.Success)
            {
                MessageBox.Show(hr.ToString());
                return;
            }

            IMailUser mu = (IMailUser)unknown;
            unknown.Dispose();

            // Now we query the following properties:
            Tags[] ptags = new Tags[] { Tags.PR_DISPLAY_NAME, Tags.PR_SMTP_ADDRESS, Tags.PR_EMAIL_ADDRESS };
            MAPI33.MapiTypes.Value[] pvals = new MAPI33.MapiTypes.Value[0];

            // Now perform query
            hr = mu.GetProps(ptags, 0, out pvals);
            for (int k = 0; k < pvals.Length; k++)
            {
                Tags attrTag = Tags.PR_DEBUG;
                string attrVal = "";

                if (pvals[k].GetType() == typeof(MAPI33.MapiTypes.MapiString))
                {
                    attrTag = ((MAPI33.MapiTypes.MapiString)pvals[k]).PropTag;
                    attrVal = ((MAPI33.MapiTypes.MapiString)pvals[k]).Value;
                }

                if (pvals[k].GetType() == typeof(MAPI33.MapiTypes.MapiUnicode))
                {
                    attrTag = ((MAPI33.MapiTypes.MapiUnicode)pvals[k]).PropTag;
                    attrVal = ((MAPI33.MapiTypes.MapiUnicode)pvals[k]).Value;
                }

                if (attrTag != Tags.PR_DEBUG && attrVal.Length > 0)
                {
                    switch (attrTag)
                    {
                        case Tags.PR_DISPLAY_NAME_A:
                        case Tags.PR_DISPLAY_NAME_W:
                            myname = attrVal;
                            break;

                        case Tags.PR_SMTP_ADDRESS_A:
                        case Tags.PR_SMTP_ADDRESS_W:
                            myaddress = attrVal;
                            break;
                        case Tags.PR_EMAIL_ADDRESS_A:
                        case Tags.PR_EMAIL_ADDRESS_W:
                            //FOR MY CASE I ONLY WANT TO USE EMAIL IF SMTP IS NOT FOUND
                            if (myaddress == "")
                                myaddress = attrVal;
                            break;
                    }
                }
            }

            mu.Dispose();
            ab.Dispose();

        }
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now