VB.Net Простая электронная почта MAPI возможна ли в HTML?

#vb.net #email #mapi #simple-mapi

#vb.net #Адрес электронной почты #мапи #просто-mapi

Вопрос:

Из того, что я прочитал, это невозможно, но я все равно спрашиваю, так как, возможно, есть альтернатива, которую я упускаю…

VB.Net Приложение Windows Forms.

Это приложение иногда нуждается в отправке электронных писем, которые создаются в почтовом клиенте пользователей, которые они затем могут редактировать и отправлять. Это не происходит автоматически; он должен быть отправлен пользователем вручную.

Мы решили использовать MAPI, так как это сделало бы его совместимым с различными почтовыми клиентами, а не требовало какой-либо формы Outlook; не все являются поклонниками MS!

Этот код работает нормально, но проблема в том, что мне нужно отправить URL-адрес в электронном письме, который разбивается на две строки и не сразу становится «кликабельным».

Я хотел бы иметь возможность отправить это в формате HTML, но MAPI, похоже, не поддерживает это.

Мы отказались от использования SMTP-клиента, поскольку это еще одна вещь, которую пользователям необходимо настроить; при использовании MAPI используется существующая учетная запись электронной почты, которую уже создали ИТ-отделы, и сведения о которой они, возможно, не захотят сообщать пользователям.

Итак, есть ли способ создать электронное письмо, которое не использует SMTP-клиент для отправки электронной почты в формате HTML и не стоит руки и ноги (он же aspose: -))?

   Public Function sendMAPI(emailAddy As String, subj As String, body As String, Optional attachement As String = "") As Boolean    Dim mapi As New SendFileTo.MAPI  'Dim emailAddy As String = getFundingEmail(cmbFundedBy.Text)  mapi.AddRecipientTo(emailAddy)   If attachement = "" Then   Else  mapi.AddAttachment(attachement)  End If  Dim q = mapi.SendMailPopup(subj, body)  If mapi.GetLastError.Contains("OK") Then   If Not UpdateUserLog(Now(), sUsername, "eMail to "   emailAddy   " created in MAPI client") Then  MessageBox.Show("Unable to update user log")  End If  Return True  Else  If Not UpdateUserLog(Now(), sUsername, "eMail to "   emailAddy   " *NOT* created in MAPI client") Then  MessageBox.Show("Unable to update user log")  End If  Return False  End If  End Function   
 Imports System Imports System.Runtime.InteropServices Imports System.IO Imports System.Collections.Generic Imports System.Windows.Forms  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_TO)  End Function   Public Function AddRecipientBCC(ByVal email As String) As Boolean  Return AddRecipient(email, howTo.MAPI_TO)  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    lt;DllImport("MAPI32.DLL")gt;  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.noteText = strBody   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 gt; 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 lt;= 0) Or (m_attachments.Count gt; 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 = 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 lt;gt; 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 lt;gt; 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 lt;= 26 Then  Return errors(m_lastError)  End If  Return "MAPI error ["   m_lastError.ToString()   "]"  End Function   ReadOnly errors() As String = New String() {"OK [0]", "User abort [1]", "General MAPI failure [2]", "MAPI login failure [3]", "Disk full [4]", "Insufficient memory [5]", "Access denied [6]", "-unknown- [7]", "Too many sessions [8]", "Too many files were specified [9]", "Too many recipients were specified [10]", "A specified attachment was not found [11]", "Attachment open failure [12]", "Attachment write failure [13]", "Unknown recipient [14]", "Bad recipient type [15]", "No messages [16]", "Invalid message [17]", "Text too large [18]", "Invalid session [19]", "Type not supported [20]", "A recipient was specified ambiguously [21]", "Message in use [22]", "Network failure [23]", "Invalid edit fields [24]", "Invalid recipients [25]", "Not supported [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 = amp;H1  Private Const MAPI_DIALOG As Integer = amp;H8  Private Const maxAttachments As Integer = 20   Enum howTo  MAPI_ORIG = 0  MAPI_TO  MAPI_CC  MAPI_BCC  End Enum   End Class   lt;StructLayout(LayoutKind.Sequential)gt;  Public Class MapiMessage  Public reserved As Integer  Public subject As String  Public noteText 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   lt;StructLayout(LayoutKind.Sequential)gt;  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   lt;StructLayout(LayoutKind.Sequential)gt;  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   

Комментарии:

1. Во-первых, это простой MAPI, и он не поддерживает HTML.

2. Спасибо, Дмитрий. Я изо всех сил пытался найти что-нибудь еще, что сработало бы! У вас есть рекомендации по чему-то еще?

3. Раньше в версии Simple MAPI для Outlook была ошибка, которая позволяла передавать HTML вместо обычного текста, но я не думаю, что это больше работает. OOM будет работать, если установлен Outlook. Если нет, вы можете вернуться к простому MAPI.

4. Как вы сказали, я уже использую простой MAPI. Мне нужно отправить электронное письмо в формате HTML

5. Вы можете использовать OOM и задать MailItem.HTMLBody свойство перед вызовом MailItem.Send .

Ответ №1:

При использовании простого MAPI () есть одна хитрость MAPISendMailW — вам нужно установить тело NULL , а также прикрепить HTML-файл. Этот файл будет использоваться в качестве тела сообщения!

Комментарии:

1. Я не думаю, что это работает с последними версиями Outlook и не работает с другими почтовыми клиентами.

2. Похоже, он работает с помощью outlook 365! Требуется дополнительное тестирование 😉

3. Похоже, это не работает с Pegasus, но это может быть ошибкой установки. Я думаю, что сейчас у нас есть кое — что, с чем мы можем работать- спасибо, Юджин