winapi - How to drop files onto .MAPIMail -


given files (or shell file objects) how invoke .mapimail registered shell extension handler them?


the question

i have files on computer:

  • c:\users\ian\appdata\local\temp\contoso_invoice_141174.pdf
  • c:\users\ian\appdata\local\temp\contoso_invoice_141173.pdf
  • c:\users\ian\appdata\local\temp\contoso_invoice_141171.pdf

that want programmatic equivalent of dropping them on .mapimail registered handler:

enter image description here

the sent to folder's mail recipient option special registered .mapimail extension:

enter image description here

which file type registered on system:

hkey_classes_root\.mapimail 

how invoke drop onto ephermeral .mapimail file?

can't in registry?

now, bad developer, , spellunk registry, .mapimail entry's default value:

clsid\{9e56be60-c50f-11cf-9a2c-00a0c90a90ce} 

extract clsid {9e56be60-c50f-11cf-9a2c-00a0c90a90ce}, , confirm class registered:

hkey_classes_root\clsid\{9e56be60-c50f-11cf-9a2c-00a0c90a90ce}     (default) = desktop shortcut     \inprocserver32         (default) = %systemroot%\system32\sendmail.dll 

and use cocreateinstance create com object:

iunknown unk = createcomobject("{9e56be60-c50f-11cf-9a2c-00a0c90a90ce}"); 

and i'm in undocumented, unsupported world, don't know interface have queryinterface for, , methods call in order.

so we're left shell programming

what i'd involving shell (pseudo-code):

ishellfolder desktop; olecheck(shgetdesktopfolder(out desktop));  list<pidl> pidls = new list<pidl>();  ulong cheaten = 0; ulong dwattributes = 0; pidl pidl;  foreach (string filename in files) {     olecheck(desktop.parsedisplayname(0, nil, filename, out cheaten, out pidl, ref dwattributes));      pidls.add(pidl); }  //get shell folder of temp folder ishellfolder tempshellfolder; desktop.parsedisplayname(0, nil, gettemporarypath, out cheaten, out pidl, ref dwattributes)); desktop.bindtoobject(pidl, nil, ishellfolder, tempshellfolder);  //i have no idea i've been doing; throwing reasonable looking code //nobody ever read  idontcare context;  tempshellfolder.getuiobjectof(0, pidls.count, pidls, idontcareanymore, nil, ref context);  

except code relies on extistance of context menu, don't have. nobody says .mapimail has in context send to menu.

i asking how drop files on .mapimail file.

and god.

why not use mapi?

because no mapi client installed when you're 32-bit application running on windows 64-bit office 64-bit installed. need able accomplish user can.

although doesn't answer question, raymond pointed out it's stupid question. nobody in right mind should trying send mail recipients. desperate!

turns out i'm not stuck. while there bitness nightmare when dealing 64-bit outlook (mapi provider) 32-bit applications (or vice versa), there 1 out.

if use just mapisendmail, , no other mapi functions, safe cross 32-bit/64-bit barrier. building mapi applications on 32-bit , 64-bit platforms:

32-bit mapi application , 64-bit outlook

32-bit mapi applications not supported run on computer installed 64-bit outlook , 64-bit windows. application developer must update , rebuild application 64-bit application 64-bit platform. because 32-bit application cannot load 64-bit msmapi32.dll file. there small number of api changes application developers must incorporate build code 64-bit environment. mapi header files have been updated these changes support 64-bit platform. can download these header files @ outlook 2010: mapi header files. developers can use same set of mapi header files build both 32-bit , 64-bit mapi applications

that makes sound hope lost. but, there is, on windows 7:

exception: mapisendmail

however, 1 function call among simple mapi , mapi elements, mapisendmail, succeed in windows-32-bit-on-windows-64-bit (wow64) or windows-64-bit-on-windows-32-bit (wow32) scenario , not result in above alert. wow64 scenario applies windows 7. figure 2 shows wow64 scenario in 32-bit mapi application calls mapisendmail on computer installed 64-bit windows 7. in scenario, mapi library makes com call launch 64-bit fixmapi application. fixmapi application implicitly links mapi library, routes function call windows mapi stub, in turn forwards call outlook mapi stub, enabling mapisendmail function call succeed.

enter image description here

so, delphi jedi user, simple send e-mail functions fail (as use too much of mapi). had create own:

procedure mapisimplesendmail(slfiles: tstrings; toemailaddress: string=''; toname: string=''); var     mapimessage: tmapimessage;     flags: longword; //  sendername: ansistring; //  senderemailaddress: ansistring;     emailsubject: ansistring;     emailbody: ansistring; //  sender: tmapirecipdesc;     recipients: packed array of tmapirecipdesc;     attachments: packed array of tmapifiledesc;     i: integer;     hr: cardinal;     es: string; const     mapi_e_unicode_not_supported = 27; //windows 8. mapi_force_unicode flag specified , unicode not supported. begin     zeromemory(@mapimessage, sizeof(mapimessage));  {   sendername := '';     senderemailaddress := '';      zeromemory(@sender, sizeof(sender));     sender.ulrecipclass := mapi_orig; //mapi_to, mapi_cc, mapi_bcc, mapi_orig     sender.lpszname := pansichar(sendername);     sender.lpszaddress := pansichar(senderemailaddress);}     mapimessage.lporiginator := nil; //pmapirecipdesc; { originator descriptor                  }      if toemailaddress <> ''     begin         setlength(recipients, 1);         recipients[0].ulrecipclass := mapi_to;         recipients[0].lpszname := lpstr(toname);         recipients[0].lpszaddress := lpstr(toemailaddress);          mapimessage.lprecips := @recipients[0]; //a value of null means there no recipients. additionally, when member null, nrecipcount member must zero.         mapimessage.nrecipcount := 1;     end     else     begin         mapimessage.lprecips := nil; //a value of null means there no recipients. additionally, when member null, nrecipcount member must zero.         mapimessage.nrecipcount := 0;     end;      mapimessage.lpszmessagetype := nil;      if slfiles.count > 0     begin         emailsubject := 'emailing: ';         emailbody :=                 '          '+#13#10+ //yes, shell create blank mail leading line of ten spaces                 'your message ready sent following file or link attachments:'+#13#10;       setlength(attachments, slfiles.count);         := 0 slfiles.count-1         begin             attachments[i].ulreserved := 0; // cardinal;        { reserved future use (must 0)     }             attachments[i].flflags := 0; // cardinal;           { flags                                   }             attachments[i].nposition := $ffffffff; //cardinal;         { character in text replaced attachment }             attachments[i].lpszpathname := pansichar(slfiles[i]);    { full path name of attachment file       }             attachments[i].lpszfilename := nil; // lpstr;         { original file name (optional)           }             attachments[i].lpfiletype := nil; // pointer;         { attachment file type (can lpmapifiletagext) }              if > 0                 emailsubject := emailsubject+', ';             emailsubject := emailsubject+extractfilename(slfiles[i]);             emailbody := emailbody+#13#10+                     extractfilename(slfiles[i]);         end;          emailbody := emailbody+#13#10+                 #13#10+                 #13#10+                 'note: protect against computer viruses, e-mail programs may prevent sending or receiving types of file attachments.  check e-mail security settings determine how attachments handled.';           mapimessage.lpfiles := @attachments[0];         mapimessage.nfilecount := slfiles.count;     end     else     begin         emailsubject := '';         emailbody := '';          mapimessage.lpfiles := nil;         mapimessage.nfilecount := 0;     end;      {         subject         emailing: 4388_888871544_mvm_10.tmp, amt3.log, swtag.log, wct845c.tmp, ~vs1830.sql          body                   <-- ten spaces         message ready sent following file or link attachments:          4388_888871544_mvm_10.tmp         amt3.log         swtag.log         wct845c.tmp         ~vs1830.sql           note: protect against computer viruses, e-mail programs may prevent sending or receiving types of file attachments.  check e-mail security settings determine how attachments handled.     }     mapimessage.lpszsubject := pansichar(emailsubject);     mapimessage.lpsznotetext := pansichar(emailbody);       flags := mapi_dialog;      hr := mapi.mapisendmail(0, 0, mapimessage, flags, 0);     case hr of     success_success: {nop}; //the call succeeded , message sent.     mapi_e_ambiguous_recipient:         begin             //es := 'a recipient matched more 1 of recipient descriptor structures , mapi_dialog not set. no message sent.';             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_ambiguous_recipient', syserrormessage(hr)]);         end;     mapi_e_attachment_not_found:         begin             //the specified attachment not found. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_attachment_not_found', syserrormessage(hr)]);         end;     mapi_e_attachment_open_failure:         begin             //the specified attachment not opened. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_attachment_open_failure', syserrormessage(hr)]);         end;     mapi_e_bad_reciptype:         begin             //the type of recipient not mapi_to, mapi_cc, or mapi_bcc. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_bad_reciptype', syserrormessage(hr)]);         end;     mapi_e_failure:         begin             //one or more unspecified errors occurred. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_failure', syserrormessage(hr)]);         end;     mapi_e_insufficient_memory:         begin             //there insufficient memory proceed. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_insufficient_memory', syserrormessage(hr)]);         end;     mapi_e_invalid_recips:         begin             //one or more recipients invalid or did not resolve address.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_invalid_recips', syserrormessage(hr)]);         end;     mapi_e_login_failure:         begin             //there no default logon, , user failed log on when logon dialog box displayed. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_login_failure', syserrormessage(hr)]);         end;     mapi_e_text_too_large:         begin             //the text in message large. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_text_too_large', syserrormessage(hr)]);         end;     mapi_e_too_many_files:         begin             //there many file attachments. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_too_many_files', syserrormessage(hr)]);         end;     mapi_e_too_many_recipients:         begin             //there many recipients. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_too_many_recipients', syserrormessage(hr)]);         end;     mapi_e_unicode_not_supported:         begin             //the mapi_force_unicode flag specified , unicode not supported.             //note  value can returned mapisendmailw only.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_unicode_not_supported', syserrormessage(hr)]);         end;     mapi_e_unknown_recipient:         begin             //a recipient did not appear in address list. no message sent.             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_unknown_recipient', syserrormessage(hr)]);         end;     mapi_e_user_abort:         begin             es := 'the user canceled 1 of dialog boxes. no message sent.';             raise exception.createfmt('error %s sending e-mail message: %s', ['mapi_e_user_abort', es]);         end;     else         raise exception.createfmt('error %d sending e-mail message: %s', [hr, syserrormessage(hr)]);     end; end; 

note: code released public domain. no attribution required.


Comments

Popular posts from this blog

c# - Operator '==' incompatible with operand types 'Guid' and 'Guid' using DynamicExpression.ParseLambda<T, bool> -