[TUTORIAL] Come inviare una mail con il client di posta installato (al...

giovedì 31 marzo 2011 - 10.07
Tag Elenco Tags  VB.NET  |  .NET 2.0  |  .NET 3.5  |  .NET 4.0  |  Windows 7  |  Windows Vista  |  Windows XP  |  Visual Studio 2010  |  Visual Studio 2008

whiteflash Profilo | Junior Member

Ciao a tutti,
molti come me si sono domandati spesso come inviare un'e-mail di posta con VB.NET, ma in più specifico che ci sia anche la possibilità di poter allegare degli allegati.
Bene ora che sono riuscito a trovare una soluzione la condivido con tutti voi, nella speranza che torni utile anche a qualcun altro

Per prima cosa vi propongo la soluzione "normale", cioè utilizzando la classica funzione integrata di VB.NET: System.Diagnostics.Process.Start
Questa vi permette di inviare un'e-mail ma SENZA la possibilità di aggiungere allegati, perchè tale funzione non è supportata ufficialmente.


Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


Questa invece è la soluzione più interessante si utilizza sfuttando l'api di windows "MAPI32.DLL"
e permette di aggiungere più destinatari automaticamente, aggiungere copie conforme nascoste, e AGGIUNGERE ALLEGATI.
[testato con Windows Live Mail e Thunderbird]

L'utilizzo è semplice:
1> Creare un file Classe di nome: SendFileTo
2> Incollare il codice sottostante al suo interno

Imports System.Runtime.InteropServices Namespace SendFileTo Class MAPI Public Function AddRecipientTo(ByVal email As String) As Boolean Return AddRecipient(email, howTo.MAPI_TO) End Function Public Function AddRecipientCC(ByVal email As String) As Boolean Return AddRecipient(email, howTo.MAPI_CC) End Function Public Function AddRecipientBCC(ByVal email As String) As Boolean Return AddRecipient(email, howTo.MAPI_BCC) End Function Public Sub AddAttachment(ByVal strAttachmentFileName As String) m_attachments.Add(strAttachmentFileName) End Sub Public Function SendMailPopup(ByVal strSubject As String, ByVal strBody As String) As Integer Return SendMail(strSubject, strBody, MAPI_LOGON_UI Or MAPI_DIALOG) End Function Public Function SendMailDirect(ByVal strSubject As String, ByVal strBody As String) As Integer Return SendMail(strSubject, strBody, MAPI_LOGON_UI) End Function <DllImport("MAPI32.DLL")> _ Private Shared Function MAPISendMail(ByVal sess As IntPtr, ByVal hwnd As IntPtr, ByVal message As MapiMessage, ByVal flg As Integer, ByVal rsv As Integer) As Integer End Function Private Function SendMail(ByVal strSubject As String, ByVal strBody As String, ByVal how As Integer) As Integer Dim msg As MapiMessage = New MapiMessage() msg.subject = strSubject msg.text = strBody.Trim msg.recips = GetRecipients(msg.recipCount) msg.files = GetAttachments(msg.fileCount) m_lastError = MAPISendMail(New IntPtr(0), New IntPtr(0), msg, how, 0) If m_lastError > 1 Then MessageBox.Show("MAPISendMail failed! " + GetLastError(), "MAPISendMail") End If Cleanup(msg) Return m_lastError End Function Private Function AddRecipient(ByVal email As String, ByVal howTo As howTo) As Boolean Dim recipient As MapiRecipDesc = New MapiRecipDesc() recipient.recipClass = CType(howTo, Integer) recipient.name = email m_recipients.Add(recipient) Return True End Function Private Function GetRecipients(ByRef recipCount As Integer) As IntPtr recipCount = 0 If m_recipients.Count = 0 Then Return 0 End If Dim size As Integer = Marshal.SizeOf(GetType(MapiRecipDesc)) Dim intPtr As IntPtr = Marshal.AllocHGlobal( m_recipients.Count * size) Dim ptr As Integer = CType(intPtr, Integer) Dim mapiDesc As MapiRecipDesc For Each mapiDesc In m_recipients Marshal.StructureToPtr(mapiDesc, CType(ptr, IntPtr), False) ptr += size Next recipCount = m_recipients.Count Return intPtr End Function Private Function GetAttachments(ByRef fileCount As Integer) As IntPtr fileCount = 0 If m_attachments Is Nothing Then Return 0 End If If (m_attachments.Count <= 0) Or (m_attachments.Count > maxAttachments) Then Return 0 End If Dim size As Integer = Marshal.SizeOf(GetType(MapiFileDesc)) Dim intPtr As IntPtr = Marshal.AllocHGlobal( m_attachments.Count * size) Dim mapiFileDesc As MapiFileDesc = New MapiFileDesc() mapiFileDesc.position = -1 Dim ptr As Integer = CType(intPtr, Integer) Dim strAttachment As String For Each strAttachment In m_attachments mapiFileDesc.name = IO.Path.GetFileName(strAttachment) mapiFileDesc.path = strAttachment Marshal.StructureToPtr(mapiFileDesc, CType(ptr, IntPtr), False) ptr += size Next fileCount = m_attachments.Count Return intPtr End Function Private Sub Cleanup(ByRef msg As MapiMessage) Dim size As Integer = Marshal.SizeOf(GetType(MapiRecipDesc)) Dim ptr As Integer = 0 If msg.recips <> IntPtr.Zero Then ptr = CType(msg.recips, Integer) Dim i As Integer For i = 0 To msg.recipCount - 1 Step i + 1 Marshal.DestroyStructure(CType(ptr, IntPtr), GetType(MapiRecipDesc)) ptr += size Next Marshal.FreeHGlobal(msg.recips) End If If msg.files <> IntPtr.Zero Then size = Marshal.SizeOf(GetType(MapiFileDesc)) ptr = CType(msg.files, Integer) Dim i As Integer For i = 0 To msg.fileCount - 1 Step i + 1 Marshal.DestroyStructure(CType(ptr, IntPtr), GetType(MapiFileDesc)) ptr += size Next Marshal.FreeHGlobal(msg.files) End If m_recipients.Clear() m_attachments.Clear() m_lastError = 0 End Sub Public Function GetLastError() As String If m_lastError <= 26 Then Return errors(m_lastError) End If Return "MAPI error [" + m_lastError.ToString() + "]" End Function ReadOnly errors() As String = New String() {"OK [0]", "Annullato dall'utente [1]", "Errore generale MAPI [2]", "Accesso MAPI fallito [3]", "Disco pieno [4]", "Memoria insufficente [5]", "Accesso negato [6]", "-sconosciuto- [7]", "Troppe sessioni [8]", "Sono stati specificati troppi files [9]", "Sono stati specificati troppi destinatari [10]", "L'allegato specificato non è disponibile [11]", "Apertura allegato fallita [12]", "Scrittura dell'allegato fallita [13]", "Destinatario sconosciuto [14]", "Tipo di destinatario non corretto [15]", "Nessun messaggio [16]", "Messaggio non valido [17]", "Testo troppo grande [18]", "Sessione non valida [19]", "Tipo non supportato [20]", "Uno dei destinatari specificati è ambiguo [21]", "Messaggio in uso [22]", "Errore di rete [23]", "Campi di modifica non vallidi [24]", "Destinatari non validi [25]", "Non supportato [26]"} Dim m_recipients As New List(Of MapiRecipDesc) Dim m_attachments As New List(Of String) Dim m_lastError As Integer = 0 Private Const MAPI_LOGON_UI As Integer = &H1 Private Const MAPI_DIALOG As Integer = &H8 Private Const maxAttachments As Integer = 20 Enum howTo MAPI_ORIG = 0 MAPI_TO MAPI_CC MAPI_BCC End Enum End Class <StructLayout(LayoutKind.Sequential)> _ Public Class MapiMessage Public reserved As Integer Public subject As String Public text As String Public messageType As String Public dateReceived As String Public conversationID As String Public flags As Integer Public originator As IntPtr Public recipCount As Integer Public recips As IntPtr Public fileCount As Integer Public files As IntPtr End Class <StructLayout(LayoutKind.Sequential)> _ Public Class MapiFileDesc Public reserved As Integer Public flags As Integer Public position As Integer Public path As String Public name As String Public type As IntPtr End Class <StructLayout(LayoutKind.Sequential)> _ Public Class MapiRecipDesc Public reserved As Integer Public recipClass As Integer Public name As String Public address As String Public eIDSize As Integer Public enTryID As IntPtr End Class End Namespace

Per utilizzare la classe per inviare una mail, si deve procedere quanto segue:
[Per il contenuto della mail in HTML, al momento non ho trovato il modo per passarglielo, se troverò una soluzione aggiornerò il post]

Dim AllegatoFile As String = "C:\.....\miofile.pdf" Dim Mapi As New SendFileTo.MAPI Mapi.AddRecipientTo("suaMail1@mail.it") Mapi.AddRecipientTo("suaMail2@mail.it") Mapi.AddRecipientCC("CopiaConformemail@mail.it") Mapi.AddRecipientBCC("CopiaConformeNascostamail@mail.it") Mapi.AddAttachment(AllegatoFile) Mapi.SendMailPopup("TITOLO DELLA MAIL", "CONTENUTO DELLA MAIL")


Attenzione: il codice API riportato nella seconda soluzione non è frutto delle mie mani, quindi anche se perfettamente funzionante, potrebbe generare eccezzioni e non mi ritengo responsabile per problemi di varia natura.

Buon lavoro!
---------------------------------------------
Newbie esperto VB.NET 2010 e WPF
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5