|
Plz send me the source & demo
as early as possible
Thank u.
Shital
dfgsd
|
|
|
|
|
|
he wants a sample html page calling it i guess !
|
|
|
|
|
I've been struggling with how to make this work with c#. Has anyone been successful?
|
|
|
|
|
 A .NET solution is slightly more tricky since we need to marshal data between managed and unmanaged code for the Win32 MAPI calls. Here's a class file you can use. I will update the article to include this along with a sample C# test application.
using System;
using System.Runtime.InteropServices;
using System.IO;
namespace SendFileTo
{
class MAPI
{
private const int MAPI_LOGON_UI = 0x00000001;
private const int MAPI_DIALOG = 0x00000008;
public static int SendMail(string strAttachmentFileName, string strSubject)
{
IntPtr session = new IntPtr(0);
IntPtr winhandle = new IntPtr(0);
MapiMessage msg = new MapiMessage();
msg.subject = strSubject;
int sizeofMapiDesc = Marshal.SizeOf(typeof(MapiFileDesc));
IntPtr pMapiDesc = Marshal.AllocHGlobal(sizeofMapiDesc);
MapiFileDesc fileDesc = new MapiFileDesc();
fileDesc.position = -1;
int ptr = (int)pMapiDesc;
string path = strAttachmentFileName;
fileDesc.name = Path.GetFileName(path);
fileDesc.path = path;
Marshal.StructureToPtr(fileDesc, (IntPtr)ptr, false);
msg.files = pMapiDesc;
msg.fileCount = 1;
return MAPISendMail(session, winhandle, msg, MAPI_LOGON_UI | MAPI_DIALOG, 0);
}
[DllImport("MAPI32.DLL")]
private static extern int MAPISendMail(IntPtr sess, IntPtr hwnd, MapiMessage message, int flg, int rsv);
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiMessage
{
public int reserved;
public string subject;
public string noteText;
public string messageType;
public string dateReceived;
public string conversationID;
public int flags;
public IntPtr originator;
public int recipCount;
public IntPtr recips;
public int fileCount;
public IntPtr files;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiFileDesc
{
public int reserved;
public int flags;
public int position;
public string path;
public string name;
public IntPtr type;
}
}
You can use it something like this.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SendFileTo;
namespace Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load_1(object sender, EventArgs e)
{
MAPI.SendMail("c://documents//menu.doc", "Here's the lunch menu");
}
}
}
-- modified at 10:14 Tuesday 12th December, 2006
|
|
|
|
|
Thanks. I'll give this a shot and see what happens.
|
|
|
|
|
Can you please tell me how to repeat the same for multiple files..
Sriharsha R
|
|
|
|
|
Here's the code. The only code I'm a little concerned with is:
int ptr = (int)ptrMapiDesc + (iFilePtr * Marshal.SizeOf(typeof(MapiFileDesc)));
This may not be safe. But I tested it and it works.
Good luck,
John
using System;
using System.Runtime.InteropServices;
using System.IO;
namespace SendFileTo
{
class MAPI
{
private const int MAPI_LOGON_UI = 0x00000001;
private const int MAPI_DIALOG = 0x00000008;
public static int SendMail(string[] aAttachments, string sSubject, string sBody)
{
IntPtr ptrSession = new IntPtr(0);
IntPtr ptrWinHandle = new IntPtr(0);
int iFiles = 0;
int iFilePtr = 0;
// Create a message
MapiMessage msg = new MapiMessage();
msg.subject = sSubject;
msg.noteText = sBody;
// Get the number of files
iFiles = aAttachments.GetLength(0);
MapiFileDesc[] fileDesc = new MapiFileDesc[iFiles];
int iSizeofMapiDesc = Marshal.SizeOf(typeof(MapiFileDesc)) * iFiles;
IntPtr ptrMapiDesc = Marshal.AllocHGlobal(iSizeofMapiDesc);
foreach(string sAttachment in aAttachments)
{
fileDesc[iFilePtr] = new MapiFileDesc();
fileDesc[iFilePtr].position = -1;
int ptr = (int)ptrMapiDesc + (iFilePtr * Marshal.SizeOf(typeof(MapiFileDesc)));
string sPath = sAttachment;
fileDesc[iFilePtr].name = Path.GetFileName(sPath);
fileDesc[iFilePtr].path = sPath;
Marshal.StructureToPtr(fileDesc[iFilePtr], (IntPtr)ptr, false);
iFilePtr++;
}
msg.files = ptrMapiDesc;
msg.fileCount = iFiles;
return(MAPISendMail(ptrSession, ptrWinHandle, msg, MAPI_LOGON_UI | MAPI_DIALOG, 0));
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiMessage
{
public int reserved;
public string subject;
public string noteText;
public string messageType;
public string dateReceived;
public string conversationID;
public int flags;
public IntPtr originator;
public int recipCount;
public IntPtr recips;
public int fileCount;
public IntPtr files;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiFileDesc
{
public int reserved;
public int flags;
public int position;
public string path;
public string name;
public IntPtr type;
}
}
|
|
|
|
|
Most excellent ! 
|
|
|
|
|
|
I've been using this for a while now and suddenly Outlook 2003 is freezing when the email arrives in my inbox. It turns out that the version of McAfee I'm using (VirusScan Enterprise v 8.0.0) has some sensitivities to emails with attachement generated like this. The causes are \ or / in the display filename and MIME type settings.
So take care when setting the filename in MapiFileDesc. After all it's only for display purposes in the email.
MapiFileDesc fileDesc;
fileDesc.lpszFileName = "something with out slashes";
Also, force the email to be text/plain by putting something in the note text This will force the email to be plain text regardless of the users preference settings (HTML/RTF/text).
MapiMessage message;
message.lpszNoteText = "blah";
For examples of how you might want to default these values, try selecting a file, right clicking and selecting Send To -> Mail recipient. Notice how Outlook sets the default values.
Let me know if you spot any other AV issues.
|
|
|
|
|
I fixed the code like this:
MapiFileDesc fileDesc;
::ZeroMemory(&fileDesc, sizeof(fileDesc));
fileDesc.nPosition = (ULONG)-1;
fileDesc.lpszPathName = szPath;
fileDesc.lpszFileName = ::PathFindFileName(szFileName); // Remove the path
It simply removes the path and just leaves the filename.
Sorted.
|
|
|
|
|
Is there any way to automatically Send the email without pressing the Send button
And
How do attach two or more files?
|
|
|
|
|
For multiple attachments use the following code:
bool SendMail(HWND hWndParent, const std::vector<cstring> &vFiles)
{
if (vFiles.size() <= 0)
return false;
if (!hWndParent || !::IsWindow(hWndParent))
return false;
HINSTANCE hMAPI = ::LoadLibraryA(_T("MAPI32.DLL"));
if (!hMAPI)
return false;
ULONG (PASCAL *SendMail)(ULONG, ULONG_PTR, MapiMessage*, FLAGS, ULONG);
(FARPROC&)SendMail = GetProcAddress(hMAPI, _T("MAPISendMail"));
if (!SendMail)
return false;
const int iNumFiles = vFiles.size();
char szSubject[_MAX_PATH];
::StrCpy(szSubject, "");
MapiFileDesc *fileDesc = new MapiFileDesc[iNumFiles];
LPSTR *szFileName = new LPSTR[iNumFiles];
for(int i = 0; i < iNumFiles; ++i)
{
szFileName[i] = new char[_MAX_PATH];
::StrCpy(szFileName[i], CT2CA(vFiles[i]) );
::ZeroMemory(&fileDesc[i], sizeof(MapiFileDesc));
fileDesc[i].nPosition = (ULONG)-1;
fileDesc[i].lpszPathName = szFileName[i];
fileDesc[i].lpszFileName = szFileName[i];
}
MapiMessage message;
::ZeroMemory(&message, sizeof(message));
message.lpszSubject = szSubject;
message.nFileCount = iNumFiles;
message.lpFiles = fileDesc;
int nError = SendMail(0, (ULONG_PTR)hWndParent, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
for(int i = 0; i < iNumFiles; ++i)
{
delete[] szFileName[i];
}
delete[] szFileName;
delete[] fileDesc;
if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)
return false;
return true;
}
Usage:
void Test()
{
std::vector<cstring> vFiles;
vFiles.push_back(_T("C:\\Test1.pfd"));
vFiles.push_back(_T("C:\\Test2.bmp"));
vFiles.push_back(_T("C:\\Test1.txt"));
SendMail(AfxGetMainWnd()->GetSafeHwnd(), vFiles);
}
Note*
In the vector, add full path of the files to be attached.
|
|
|
|
|
#ifndef __SENDFILETO_H__
#define __SENDFILETO_H__
#include <mapi.h>
#include <atlbase.h>
#define MAX_MESSAGE 2048
class CSendFileTo
{
public:
bool SendMail(HWND hWndParent, CString const &strAttachmentFileName, CString const &strSubject=_T("")
, CString messageBody=_T(""))
{
CStringArray strArray;
strArray.Add(strAttachmentFileName);
return (SendMail(hWndParent, strArray, strSubject, messageBody));
}
bool SendMail(HWND hWndParent, CStringArray const &strAttachmentFileNames, CString const &strSubject=_T(""),
CString messageBody=_T(""))
{
if (strAttachmentFileNames.GetSize()<=0)
return false;
if (!hWndParent || !::IsWindow(hWndParent))
return false;
HINSTANCE hMAPI = ::LoadLibrary(_T("MAPI32.DLL"));
if (!hMAPI)
return false;
ULONG (PASCAL *SendMail)(ULONG, ULONG_PTR, MapiMessage*, FLAGS, ULONG);
(FARPROC&)SendMail = GetProcAddress(hMAPI, "MAPISendMail");
if (!SendMail)
return false;
USES_CONVERSION;
char szSubject[_MAX_PATH];
int iNumFiles=strAttachmentFileNames.GetSize();
::strcpy(szSubject, W2A(strSubject.GetString()));
MapiFileDesc *fileDesc = new MapiFileDesc[iNumFiles];
LPSTR *szFileName = new LPSTR[iNumFiles];
for(int i = 0; i < iNumFiles; ++i)
{
szFileName[i] = new char[_MAX_PATH];
::strcpy(szFileName[i], W2A(strAttachmentFileNames[i]) );
::ZeroMemory(&fileDesc[i], sizeof(MapiFileDesc));
fileDesc[i].nPosition = (ULONG)-1;
fileDesc[i].lpszPathName = szFileName[i];
fileDesc[i].lpszFileName = szFileName[i];
}
MapiMessage message;
::ZeroMemory(&message, sizeof(message));
message.lpszSubject = szSubject;
message.nFileCount = iNumFiles;
message.lpFiles = fileDesc;
LPSTR messageBodyArray = new char[MAX_MESSAGE];
strncpy (messageBodyArray, W2A(messageBody.GetString()), MAX_MESSAGE);
message.lpszNoteText = messageBodyArray;
int nError = SendMail(0, (ULONG_PTR)hWndParent, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
for(int i = 0; i < iNumFiles; ++i)
{
delete[] szFileName[i];
}
delete[] szFileName;
delete[] fileDesc;
delete messageBodyArray;
if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)
return false;
return true;
}
};
#endif
|
|
|
|
|
I have got the code Working with my MFC project. However, I have 2 questions.
1. You mentioned in the article, "To remove the Modeness, simply change the hWnd parameter to HWND_DESKTOP". I tried to put both "HWND_DESKTOP" and "NULL" as the hWnd, but in both cases, mail dialog appears still be Application Modal to my main program. And clicking on the "Minimize" button on mail dialog simply fails to minimize the dialog. Do you have any idea on this?
2. When the Mail dialog pops up, instead of sending it, if I click on the 'save' button, found that the mail is saved into my INBOX folder. By right, the mail should be saved into the DRAFT folder, shouldn't it? Is there any option that we could set somewhere to correct this problem when using the MAPI_SENDMAIL function? I am using Ms Outlook 2003.
Thank you in advance if you could help on either of the problem.
|
|
|
|
|
I have the same question about your question2.
who can help us?
Thank you!
|
|
|
|
|
I have fixed Outlook modal behaver with a new thread started in place of SendMail function call before. Function called by thread SendMailBackground call MAPISendMail. Message is not modal any more in my application but it is still modal in Outlook.
code sample:
MapiFileDesc* mapi_files;
mapi_files = new MapiFileDesc[num_of_files];
MapiFileDesc* current_file = mapi_files;
for (i=0; i<num_of_files; i++)
="" {=""
="" zeromemory(current_file,="" sizeof(mapifiledesc));
="" current_file-="">nPosition = (ULONG)-1;
current_file->lpszPathName = localPaths[i];
current_file->lpszFileName = localPaths[i];
current_file++;
}
MapiMessage* message = new MapiMessage;
ZeroMemory(message, sizeof(MapiMessage));
message->lpszSubject = szSubject);
message->nFileCount = num_of_files;
message->lpFiles = mapi_files;
//SendMail(0, (unsigned long)HWND_DESKTOP, message, API_LOGON_UI|MAPI_DIALOG, 0);
DWORD dwThreadId = 0;
CreateThread(NULL, 0,
SendMailBackroung, (LPVOID)message, 0, &dwThreadId);
// end of message sending in primary thread
// SendMailBackground function
DWORD static WINAPI SendMailBackroung(LPVOID ptr)
{
MapiMessage* message = (MapiMessage*)ptr;
ULONG (PASCAL *SendMail)(LHANDLE, ULONG, MapiMessage*, FLAGS, ULONG);
DWORD isOK = 1;
int i = 0;
HINSTANCE hMAPI = LoadLibrary(_T("MAPI32.DLL"));
if(hMAPI)
{
(FARPROC&)SendMail = GetProcAddress(hMAPI, "MAPISendMail");
if (SendMail)
isOK = SendMail(0, (ULONG)HWND_DESKTOP, message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
FreeLibrary(hMAPI);
}
for (i=0; i<message->nFileCount; i++)
{
delete message->lpFiles->lpszFileName;
}
delete message->lpFiles;
delete message->lpszSubject;
delete message->lpszNoteText;
delete message;
return isOK;
}
|
|
|
|
|
Has anyone done this in Borland C++?
|
|
|
|
|
I have got it going now with C++ Builder sort of. I have set the following
#define TCHAR char
#define _T LPCSTR
#define CString char
plus a few other minor changes.
This starts outlook express and everything appears correct however the New Message Window is locked up apart from being able to type into the TO: edit box. So you can't send the mail unless you enter Control N for a new window, then delete new window then the original window works fine as it should. Any ideas?
|
|
|
|
|
Figured it out. Use Hide() to give Outlook Express control followed by a Show() to give it back to the application.
|
|
|
|
|
Can you post the whole list of changes for borland c++ builder please?
|
|
|
|
|
This Borland C++ version is a simple function that sends attachments, subject and body. The only thing missing I would like is an automatic SEND funcion
// EmailTo.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#include <assert.h>
#include <mapidefs.h>
#include <mapi.h>
#pragma hdrstop
#include "EmailTo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
int EMailTo(TCustomForm *MainForm, HWND hWndParent, string strAddress, string strName, string strAttachmentFileName,
string strSubject, string strBody)
{ // Send an email with attachments
// Typical call:
// EMailTo(this, m_hWnd, "sales@mycompany.com", "sales", "c:\\Devel_Test_Email\\attachment.txt",
// "Here's the subject", "Here is the body");
//
// by JLB 22 May 2006
//
// This was an adaption of an MFC routine
// There were several routines to SetFocus and other things that I have had real bad experiences with
// so they are all commented out and the Hide() and Show() commands take care of them all
// The original MFC commmands and the equivalent BCB commands commented out as follows:
// The MFC commands are commented out with //MFC// and the equivalent
// Borland commands are commented out with //BCB//
// If a command does both thenit is commented out with //BCB&MFC//
//
HINSTANCE hMail = NULL;
hMail = ::LoadLibraryA("MAPI32.DLL");
if (hMail == NULL)
{
//MessageBox(AFX_IDP_FAILED_MAPI_LOAD);
Application->MessageBox("Failed to load MAPI32.DLL","Email Error - Send Failed",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
return 1;
}
assert(hMail != NULL);
ULONG (PASCAL *lpfnSendMail)(ULONG, ULONG, MapiMessage*, FLAGS, ULONG);
(FARPROC&)lpfnSendMail = GetProcAddress(hMail, "MAPISendMail");
if (lpfnSendMail == NULL)
{
//MessageBox(AFX_IDP_INVALID_MAPI_DLL);
Application->MessageBox("Invalid MAPI32.DLL","Email Error - Send Failed",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
return 1;
}
assert(lpfnSendMail != NULL);
TCHAR szOriginator[_MAX_PATH];
TCHAR szAddress[_MAX_PATH];
TCHAR szName[_MAX_PATH];
TCHAR szFileName[_MAX_PATH];
TCHAR szPath[_MAX_PATH];
TCHAR szSubject[_MAX_PATH];
//TCHAR szBody[_MAX_PATH];
int iMaxPath = _MAX_PATH; // _MAX_PATH seems to be 260 so increase it as it doesn't seem to do any damage
char szBody[1024]; // as _MAX_PATH seems to be a minimum rather than a maximum and
// // lpszNoteText is a LPTSTR anyway so this could be increased if required
// Set the attachments
//
strcpy(szAddress, "SMTP:"); // Start with SMTP:
strcat(szAddress, strAddress.c_str()); // Now append the actual email address
strcpy(szName, strName.c_str()); // Name in To: box eg Authorization
strcpy(szPath, strAttachmentFileName.c_str()); // Attachment file name
strcpy(szFileName, strAttachmentFileName.c_str()); // If NULL then taken from szPath
strcpy(szSubject, strSubject.c_str()); // Subject
if(strBody.size() > 1023)
{ // See note just above about increasing body size
Application->MessageBox("Text Body Too Large","Email Error - Text Body > 1023 characters",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
return 1;
}
strcpy(szBody, strBody.c_str()); // Body separated by "\n" for carriage returns
//
// Set the file description
//
MapiFileDesc fileDesc;
::ZeroMemory(&fileDesc, sizeof(fileDesc));
fileDesc.nPosition = (ULONG)-1;
fileDesc.lpszPathName = szPath;
fileDesc.lpszFileName = szFileName;
//
// make a recipient
//
MapiRecipDesc recipDesc;
::ZeroMemory(&recipDesc, sizeof(recipDesc));
recipDesc.lpszName = szName; // Name in To: box eg Authorization
recipDesc.ulRecipClass = MAPI_TO; // As in MAPI_CC or MAPI_BC etc
recipDesc.lpszAddress = szAddress; // Actual email address prepended with SMTP:
//
//
// make an originator - Not used
//
strcpy(szOriginator, "originator@mycompany.com");
MapiRecipDesc origDesc;
::ZeroMemory(&origDesc, sizeof(origDesc));
origDesc.lpszName = szName; //
origDesc.ulRecipClass = MAPI_ORIG; // As in MAPI_CC or MAPI_BC etc
origDesc.lpszAddress = szOriginator; // Actual email address prepended with SMTP:
//
// prepare the message
//
// Set the Subject
MapiMessage message;
::ZeroMemory(&message, sizeof(message));
message.lpszSubject = szSubject;
message.nFileCount = 1;
message.lpFiles = &fileDesc;
message.nRecipCount = 1;
//message.lpOriginator = &origDesc;
message.lpRecips = &recipDesc;
message.lpszNoteText = szBody;
// prepare for modal dialog box
//MFC// AfxGetApp()->EnableModeless(FALSE);
//BCB// HRESULT STDMETHODCALLTYPE EnableModeless(FALSE);
/////HWND hWndTop;
/////HWND* pParentWnd = HWND::GetSafeOwner(NULL, &hWndTop);
// some extra precautions are required to use
// MAPISendMail as it tends to enable the parent
// window in between dialogs (after the login
// dialog, but before the send not dialog).
//MFC//pParentWnd->SetCapture();
//BCB// SetCapture(pParentWnd);
//BCB&MFC// ::SetFocus(NULL);
//MFC// pParentWnd->m_nFlags |= WF_STAYDISABLED;
MainForm->Hide();
int nError = lpfnSendMail(0, (ULONG_PTR)hWndParent, &message, MAPI_LOGON_UI|MAPI_DIALOG, 0);
// after returning from the MAPISendMail call,
// the window must be re-enabled and focus
// returned to the frame to undo the workaround
// done before the MAPI call.
//BCB&MFC// ::ReleaseCapture();
//MFC// pParentWnd->m_nFlags &= ~WF_STAYDISABLED;
MainForm->Show();
//MFC// pParentWnd->EnableWindow(TRUE);
//BCB&MFC// ::SetActiveWindow(NULL);
//MFC// pParentWnd->SetActiveWindow();
//MFC// pParentWnd->SetFocus();
//MFC// if (hWndTop != NULL)
//MFC// ::EnableWindow(hWndTop, TRUE);
//MFC// AfxGetApp()->EnableModeless(TRUE);
if (nError != SUCCESS_SUCCESS && nError != MAPI_USER_ABORT && nError != MAPI_E_LOGIN_FAILURE)
{
// AfxMessageBox(AFX_IDP_FAILED_MAPI_SEND);
Application->MessageBox("Failed to send email","Email Error - Send Failed",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
return 1;
}
::FreeLibrary(hMail);
return 0;
}
=======================================================================
// EmailTo.h
//---------------------------------------------------------------------------
#include <iomanip>
#ifndef EmailToH
#define EmailToH
//---------------------------------------------------------------------------
using namespace std;
int EMailTo(TCustomForm *MainForm, HWND hWndParent, string strAddress, string StrName, string strAttachmentFileName,
string strSubject, string strBody);
#endif
|
|
|
|
|
Hi All,
I tried to send an e-mail and attachment out via Outlook 2003. The e-mail dialog comes up with the right recipient and I 'Send' it. My backend mailer is Exchange Server.
However, a couple of seconds later, I get an undeliverable message error.
Your message did not reach some or all of the intended recipients.
Subject: Error report for xxx.exe
Sent: 15-Mar-06 12:21
The following recipient(s) could not be reached:
'Software Support' on 15-Mar-06 12:21
None of your e-mail accounts could send to this recipient.
When I looked at the OutBox copy of the message there is no 'Sender' and when I dbl-click on the 'To' address, I see a questionable E-mail type - it's the recipient e-mail address. I would have expected it to be 'SMTP', shouldn't I?
If anyone has an idea what is going on here, please let me know.
Thanks in Advance!
Corey.
-- modified at 14:23 Wednesday 15th March, 2006
|
|
|
|
|
Sounds like a malformed string somewhere that causing Exchange Server to barf. Send me the code (fragement) and I'll have a look.
|
|
|
|
|