Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Sending Email using MAPI33

Posted on 2004-09-30
6
Medium Priority
?
3,099 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 2000 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

926 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