[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 3113
  • Last Modified:

Sending Email using MAPI33

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
masoncooper
Asked:
masoncooper
1 Solution
 
muellerfanCommented:
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
 
muellerfanCommented:
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
 
masoncooperAuthor Commented:
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
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
muellerfanCommented:
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
 
grace627Commented:

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
 
YousefiCommented:
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

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now