2011-02-22 5 views
0

제 문제는 C#으로 파일을 기본 메일 클라이언트에 첨부하여 사용자에게 보여줄 필요가 있다는 것입니다. 이는 마치 mailto:을 사용하는 것과 같습니다. 기본 메일 클라이언트를 사용하여 첨부 파일이있는 이메일을 보내는 간단한 방법이 있습니까?

나는이 post on the subject를 읽을 수 있지만 몇 가지 문제가있다 :

  1. 내가 첨부 공식적으로 지원하지 않기 때문에 mailto를 사용하지 않습니다.
  2. System.Net.Mail과 SMTP 클래스 (승인 된 응답에 제공된 코드)를 사용할 때 메일을 보내는 대신 사용자가 처리 할 수있는 메시지를 표시하는 방법을 모르겠습니다. 이것이 가능한지 확실하지 않습니다.
  3. 위의 (# 2) 해결책을 사용할 때 사용자의 전자 메일 서버를 얻는 방법을 모르겠습니다.
  4. 아래의 대답에서 코드 프로젝트 솔루션은 MAPI32.DLL에 대한 사용자 지정 래퍼를 사용하여 제공됩니다. 여기서 문제는이 솔루션에 대한 기사 작성자가 지정한 라이센스 계약이 프로젝트에 대한 요구 사항과 충돌한다는 것입니다.
  5. 인해 시간 제한에 내가

그래서 내 자신의 MAPI 래퍼 쓸 수 없습니다,이 문제에 대한 다른 간단한 해결책이있다? .NET으로 미리 채워진 첨부 파일을 사용하여 기본 메일 클라이언트를 팝업하는 또 다른 간단한 방법이 있습니까? 어쩌면 다른 MAPI 랩퍼 일 수도 있지만 매우 엄격한 라이센스가있는 랩퍼 일 수 있습니까?

+0

그냥 궁금 : 어떤 방법으로 프로젝트와 [코드 프로젝트 오픈 라이선스 (http://www.codeproject.com/info/cpol10.aspx) 충돌합니까? 그것은 내게 매우 관대 해 보인다. – Justin

+0

아, 방금 본 것 : "실행 파일 또는 소스 코드의 모든 복사본과 함께 본 라이센스의 사본 또는 URI (Uniform Resource Identifier)를 포함해야합니다." – Justin

+0

예. 섹션 5.b. 및 5.e. 우리에게 문제를 제기하십시오. 5.b. 저자에게 명시 적으로 신용을 부여하지 않아서 문제라고 생각합니다. 우리는 신용을 얻지 않지만 그것을주지 마십시오. 어쨌든, 제 동료는이 두 섹션으로 인하여 문제가 해결되었다고 말했습니다. –

답변

3

는 .NET의 MAPI 래퍼은 참으로 최적의 솔루션입니다 - 많은 결과 "MAPI .NET 래퍼 '의 구글 반환이있다, 나는 이들 중 하나가 적절한 라이센스가 되리라 확신합니다 :

+0

두 번째 링크는 메일 전송과 아무 관련이없는 것 같습니다. 예는 비디오/오디오 액세스를 보여줍니다. – olorin

+0

링크 된 코드는 주로 Exchange와 함께 작동하도록 만들어진 * 확장 * MAPI 용입니다. 아직 간단한 * MAPI 라이브러리를 찾지 못했습니다. –

3

여기에 포함되지 않은 첨부 파일이 만족 스럽다면 작업을 수행 할 수있는 많은 코드가 있습니다. 이것은 내가 이미 대안을 찾았 음에 틀림없는 확실한 OP가 아닌 다른 사람들에게 더 많은 것입니다. 누락 된 내용이 있으면 주석을 추가하고 필요한 내용을 추가하겠습니다. 즐겨!

public class MailMessage 
    { 
    #region Constants and Fields 

    private readonly string _body; 

    private readonly string _subject; 

    private readonly List<MapiFileDesc> _attachments; 

    private readonly List<MapiRecipDesc> _recipients; 

    #endregion 

    #region Constructors and Destructors 

    private MailMessage() 
    { 
    } 

    public MailMessage(
     string subject, string body, IEnumerable<MailAttachment> attachments, IEnumerable<MailRecipient> recipients) 
    { 
     this._subject = subject; 
     this._body = body; 

     this._attachments = new List<MapiFileDesc>(); 
     this._recipients = new List<MapiRecipDesc>(); 

     if (attachments != null) 
     { 
     foreach (var attachment in attachments) 
     { 
      _attachments.Add(attachment.GetMapiFileDesc()); 
     } 
     } 

     if (recipients != null) 
     { 
     foreach (var recipient in recipients) 
     { 
      _recipients.Add(recipient.GetMapiRecipDesc()); 
     } 
     } 
    } 

    #endregion 

    #region Public Methods 

    public void ShowDialog() 
    { 
     int result = this.ShowMail(); 

     if (!IsSuccess(result)) 
     { 
     throw new Exception(GetMapiErrorMessage(result)); 
     } 
    } 

    #endregion 

    #region Methods 

    private int ShowMail() 
    { 
     var message = new MapiMessage(); 

     message.Subject = this._subject; 
     message.NoteText = this._body; 

     int attachmentCount; 
     message.Files = AllocMapiDescArray(_attachments, out attachmentCount); 
     message.FileCount = attachmentCount; 

     int recipientCount; 
     message.Recipients = AllocMapiDescArray(_recipients, out recipientCount); 
     message.RecipientCount = recipientCount; 

     int error = Mapi32.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, Mapi32.MAPI_DIALOG, 0); 

     DeallocMapiDescArray<MapiFileDesc>(message.Files, message.FileCount); 
     DeallocMapiDescArray<MapiRecipDesc>(message.Recipients, message.RecipientCount); 

     return error; 
    } 

    private static IntPtr AllocMapiDescArray<T>(ICollection<T> mapiDescCollection, out int mapiDescCount) 
    { 
     IntPtr mapiMapiDescArrayPtr = IntPtr.Zero; 
     mapiDescCount = 0; 

     if (mapiDescCollection != null && mapiDescCollection.Count > 0) 
     { 
     int mapiDescSize = Marshal.SizeOf(typeof(T)); 
     mapiMapiDescArrayPtr = Marshal.AllocHGlobal(mapiDescCollection.Count * mapiDescSize); 

     var tmp = (int)mapiMapiDescArrayPtr; 
     foreach (var mapiDesc in mapiDescCollection) 
     { 
      Marshal.StructureToPtr(mapiDesc, (IntPtr)tmp, false); 
      tmp += mapiDescSize; 
     } 

     mapiDescCount = mapiDescCollection.Count; 
     } 

     return mapiMapiDescArrayPtr; 
    } 

    private static void DeallocMapiDescArray<T>(IntPtr mapiDescArrayPtr, int mapiDescArrayCount) 
    { 
     if (mapiDescArrayPtr != IntPtr.Zero) 
     { 
     int mapiDescSize = Marshal.SizeOf(typeof(T)); 

     var tmp = (int)mapiDescArrayPtr; 
     for (int i = 0; i < mapiDescArrayCount; i++) 
     { 
      Marshal.DestroyStructure((IntPtr)tmp, typeof(T)); 
      tmp += mapiDescSize; 
     } 
     Marshal.FreeHGlobal(mapiDescArrayPtr); 
     } 
    } 

    private static bool IsSuccess(int errorCode) 
    { 
     return (errorCode == Mapi32.SUCCESS_SUCCESS || errorCode == Mapi32.MAPI_USER_ABORT); 
    } 

    private static string GetMapiErrorMessage(int errorCode) 
    { 
     // This should be localized 

     string error = string.Empty; 

     switch (errorCode) 
     { 
     case Mapi32.MAPI_USER_ABORT: 
      error = "User Aborted."; 
      break; 
     case Mapi32.MAPI_E_FAILURE: 
      error = "MAPI Failure."; 
      break; 
     case Mapi32.MAPI_E_LOGIN_FAILURE: 
      error = "Login Failure."; 
      break; 
     case Mapi32.MAPI_E_DISK_FULL: 
      error = "MAPI Disk full."; 
      break; 
     case Mapi32.MAPI_E_INSUFFICIENT_MEMORY: 
      error = "MAPI Insufficient memory."; 
      break; 
     case Mapi32.MAPI_E_BLK_TOO_SMALL: 
      error = "MAPI Block too small."; 
      break; 
     case Mapi32.MAPI_E_TOO_MANY_SESSIONS: 
      error = "MAPI Too many sessions."; 
      break; 
     case Mapi32.MAPI_E_TOO_MANY_FILES: 
      error = "MAPI too many files."; 
      break; 
     case Mapi32.MAPI_E_TOO_MANY_RECIPIENTS: 
      error = "MAPI too many recipients."; 
      break; 
     case Mapi32.MAPI_E_ATTACHMENT_NOT_FOUND: 
      error = "MAPI Attachment not found."; 
      break; 
     case Mapi32.MAPI_E_ATTACHMENT_OPEN_FAILURE: 
      error = "MAPI Attachment open failure."; 
      break; 
     case Mapi32.MAPI_E_ATTACHMENT_WRITE_FAILURE: 
      error = "MAPI Attachment Write Failure."; 
      break; 
     case Mapi32.MAPI_E_UNKNOWN_RECIPIENT: 
      error = "MAPI Unknown recipient."; 
      break; 
     case Mapi32.MAPI_E_BAD_RECIPTYPE: 
      error = "MAPI Bad recipient type."; 
      break; 
     case Mapi32.MAPI_E_NO_MESSAGES: 
      error = "MAPI No messages."; 
      break; 
     case Mapi32.MAPI_E_INVALID_MESSAGE: 
      error = "MAPI Invalid message."; 
      break; 
     case Mapi32.MAPI_E_TEXT_TOO_LARGE: 
      error = "MAPI Text too large."; 
      break; 
     case Mapi32.MAPI_E_INVALID_SESSION: 
      error = "MAPI Invalid session."; 
      break; 
     case Mapi32.MAPI_E_TYPE_NOT_SUPPORTED: 
      error = "MAPI Type not supported."; 
      break; 
     case Mapi32.MAPI_E_AMBIGUOUS_RECIPIENT: 
      error = "MAPI Ambiguous recipient."; 
      break; 
     case Mapi32.MAPI_E_MESSAGE_IN_USE: 
      error = "MAPI Message in use."; 
      break; 
     case Mapi32.MAPI_E_NETWORK_FAILURE: 
      error = "MAPI Network failure."; 
      break; 
     case Mapi32.MAPI_E_INVALID_EDITFIELDS: 
      error = "MAPI Invalid edit fields."; 
      break; 
     case Mapi32.MAPI_E_INVALID_RECIPS: 
      error = "MAPI Invalid Recipients."; 
      break; 
     case Mapi32.MAPI_E_NOT_SUPPORTED: 
      error = "MAPI Not supported."; 
      break; 
     case Mapi32.MAPI_E_NO_LIBRARY: 
      error = "MAPI No Library."; 
      break; 
     case Mapi32.MAPI_E_INVALID_PARAMETER: 
      error = "MAPI Invalid parameter."; 
      break; 
     } 

     return string.Format("Error sending email. Error: {0} (code = {1}).", error, errorCode); 
    } 

    #endregion 
    } 

    public class MailAttachment 
    { 
    private string _attachmentFilePath; 

    public MailAttachment(string attachmentFilePath) 
    { 
     _attachmentFilePath = attachmentFilePath; 
    } 

    public MapiFileDesc GetMapiFileDesc() 
    { 
     var mapiFileDesc = new MapiFileDesc(); 

     mapiFileDesc.Position = -1; 
     mapiFileDesc.Path = _attachmentFilePath; 
     mapiFileDesc.Name = Path.GetFileName(_attachmentFilePath); 

     return mapiFileDesc; 
    } 
    } 



    public class MailRecipient 
    { 
    #region Constants and Fields 

    public string _emailAddress; 

    public string _displayName; 

    public MailRecipientType _mailRecipientType = MailRecipientType.To; 

    #endregion 

    #region Constructors and Destructors 

    public MailRecipient(string emailAddress, string displayName, MailRecipientType mailRecipientType) 
    { 
     this._emailAddress = emailAddress; 
     this._displayName = displayName; 
     this._mailRecipientType = mailRecipientType; 
    } 

    #endregion 

    #region Methods 

    public MapiRecipDesc GetMapiRecipDesc() 
    { 
     var recipDesc = new MapiRecipDesc(); 

     if (this._displayName == null) 
     { 
     recipDesc.Name = this._emailAddress; 
     } 
     else 
     { 
     recipDesc.Name = this._displayName; 
     recipDesc.Address = this._emailAddress; 
     } 

     recipDesc.RecipientClass = (int)this._mailRecipientType; 

     return recipDesc; 
    } 

    #endregion 
    } 

    public enum MailRecipientType 
    { 
    To = 1, 
    CC = 2, 
    BCC = 3 
    } ; 

    internal class Mapi32 
    { 
    #region Constants and Fields 

    public const int MAPI_DIALOG = 0x8; 

    public const int MAPI_E_AMBIGUOUS_RECIPIENT = 21; 

    public const int MAPI_E_ATTACHMENT_NOT_FOUND = 11; 

    public const int MAPI_E_ATTACHMENT_OPEN_FAILURE = 12; 

    public const int MAPI_E_ATTACHMENT_WRITE_FAILURE = 13; 

    public const int MAPI_E_BAD_RECIPTYPE = 15; 

    public const int MAPI_E_BLK_TOO_SMALL = 6; 

    public const int MAPI_E_DISK_FULL = 4; 

    public const int MAPI_E_FAILURE = 2; 

    public const int MAPI_E_INSUFFICIENT_MEMORY = 5; 

    public const int MAPI_E_INVALID_EDITFIELDS = 24; 

    public const int MAPI_E_INVALID_MESSAGE = 17; 

    public const int MAPI_E_INVALID_PARAMETER = 998; 

    public const int MAPI_E_INVALID_RECIPS = 25; 

    public const int MAPI_E_INVALID_SESSION = 19; 

    public const int MAPI_E_LOGIN_FAILURE = 3; 

    public const int MAPI_E_MESSAGE_IN_USE = 22; 

    public const int MAPI_E_NETWORK_FAILURE = 23; 

    public const int MAPI_E_NOT_SUPPORTED = 26; 

    public const int MAPI_E_NO_LIBRARY = 999; 

    public const int MAPI_E_NO_MESSAGES = 16; 

    public const int MAPI_E_TEXT_TOO_LARGE = 18; 

    public const int MAPI_E_TOO_MANY_FILES = 9; 

    public const int MAPI_E_TOO_MANY_RECIPIENTS = 10; 

    public const int MAPI_E_TOO_MANY_SESSIONS = 8; 

    public const int MAPI_E_TYPE_NOT_SUPPORTED = 20; 

    public const int MAPI_E_UNKNOWN_RECIPIENT = 14; 

    public const int MAPI_LOGON_UI = 0x1; 

    public const int MAPI_USER_ABORT = 1; 

    public const int SUCCESS_SUCCESS = 0; 

    #endregion 

    #region Public Methods 

    [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)] 
    public static extern int MAPILogon(IntPtr hwnd, string prf, string pw, int flg, int rsv, ref IntPtr sess); 

    [DllImport("MAPI32.DLL")] 
    public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv); 

    #endregion 
    } 

    [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 = IntPtr.Zero; 
    } 

    [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 = IntPtr.Zero; 

    public int RecipientCount; 

    public IntPtr Recipients = IntPtr.Zero; 

    public int FileCount; 

    public IntPtr Files = IntPtr.Zero; 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
    public class MapiRecipDesc 
    { 
    public int Reserved; 

    public int RecipientClass; 

    public string Name; 

    public string Address; 

    public int eIDSize; 

    public IntPtr EntryID = IntPtr.Zero; 
    } 
+2

64 비트 시스템에서 Marshal.AllocHGlobal은 32 비트 주소 공간보다 높은 주소를 반환 할 수 있습니다. IntPtr (64 비트)가 int (32 비트)로 형변환됨에 따라이 코드는 산술 오버플로 예외와 함께 실패합니다. "OverflowException : 산술 연산으로 인해 오버플로가 발생했습니다." 대신 ToInt64() 및 IntPtr (long)을 사용하십시오. 'code' – MRoc

관련 문제