Salut, je travaille sur une application WPF (en utilisant c #).
J'ai besoin d'une fonctionnalité permettant aux utilisateurs d'envoyer des fichiers (fichiers audio) en pièces jointes par e-mail. J'ai essayé d'utiliser l'espace de noms Microsoft.Office.Interop.Outlook.Application
Mais il ouvre Outlook et ne fonctionnera pas si Outlook n'est pas installé sur l'ordinateur du client.
J'ai essayé d'utiliser les classes SmtpClient()
et MailMessage()
de l'espace de noms System.Net.Mail
Mais son client de messagerie ne s'ouvre pas. Son envoi d'un courrier via un serveur prédéfini (peut être un problème car je ne sais pas quel est le domaine de messagerie par défaut de mon client. Ce lien a toutes les choses dont j'ai besoin et son bon fonctionnement.
Mais là, ils ont utilisé l'attribut DllImport et de nombreux problèmes peuvent survenir (d'après ce que je peux comprendre) en utilisant cette méthode. Je n'ai aucune idée du code managé et non managé donc je ne peux pas comprendre quel est le problème. Est-il OK de suivre l'exemple du lien ci-dessus. Sinon pourquoi?
Pouvez-vous dire ou fournir des liens sur la façon d'aborder mon problème
Nous pouvons utiliser le fait que la plupart des clients de messagerie prennent en charge le format de fichier .EML à charger.
Donc, si nous étendons la classe System.Net.Mail.MailMessage de manière à ce qu'elle puisse être enregistrée dans le système de fichiers en tant que fichier .EML. Le fichier résultant peut être ouvert avec le client de messagerie par défaut à l'aide de Process.Start (nom de fichier)
Pour que cela fonctionne correctement, nous devons ajouter une ligne contenant "X-Unsent: 1" au fichier .EML. Cette ligne indique au client de messagerie qui charge le fichier .EML que le message doit être présenté en mode "Nouveau message".
Utilisez le paramètre bool "addUnsentHeader" de la méthode d'extension pour ajouter cette ligne au fichier .EML
La méthode d'extension ressemble à ceci:
using System;
using System.IO;
using System.Net.Mail;
using System.Reflection;
namespace Fsolutions.Fbase.Common.Mail
{
public static class MailUtility
{
//Extension method for MailMessage to save to a file on disk
public static void Save(this MailMessage message, string filename, bool addUnsentHeader = true)
{
using (var filestream = File.Open(filename, FileMode.Create))
{
if (addUnsentHeader)
{
var binaryWriter = new BinaryWriter(filestream);
//Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode
binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));
}
var Assembly = typeof(SmtpClient).Assembly;
var mailWriterType = Assembly.GetType("System.Net.Mail.MailWriter");
// Get reflection info for MailWriter contructor
var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
// Construct MailWriter object with our FileStream
var mailWriter = mailWriterContructor.Invoke(new object[] { filestream });
// Get reflection info for Send() method on MailMessage
var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null);
// Finally get reflection info for Close() method on our MailWriter
var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
// Call close method
closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
}
}
}
}
Utilisez la méthode d'extension comme ceci:
var mailMessage = new MailMessage();
mailMessage.From = new MailAddress("[email protected]");
mailMessage.Subject = "Your subject here";
mailMessage.IsBodyHtml = true;
mailMessage.Body = "<span style='font-size: 12pt; color: red;'>My HTML formatted body</span>";
mailMessage.Attachments.Add(new Attachment("C://Myfile.pdf"));
var filename = "C://Temp/mymessage.eml";
//save the MailMessage to the filesystem
mailMessage.Save(filename);
//Open the file with the default associated application registered on the local machine
Process.Start(filename);
Avez-vous essayé d'utiliser System.Diagnostics.Process.Start()
avec une ligne de commande appropriée?
mailto:[email protected]?subject=an email&body=see attachment&attachment="/files/audio/attachment.mp3"
Le &attachment
switch vous permet de spécifier un nom de fichier.
D'accord, je me bats pour ce travail mais prétendument cela peut être fait. Je lis actuellement à travers ce monstre et je vous répondrai.
Vous pouvez demander au shell Windows d'ouvrir une URL mailto:
var url = "mailto:[email protected]";
Process.Start(url);
Vous devez être using System.Diagnostics
.
Vous pouvez définir différentes parties du message comme le sujet et le corps comme décrit dans RFC 6068
var url = "mailto:[email protected]?subject=Test&body=Hello";
Malheureusement, le protocole mailto ne prend pas en charge les pièces jointes même si certains clients de messagerie peuvent avoir un moyen de gérer cela.
J'ai utilisé la classe d'assistance suivante.
class MAPI
{
public bool AddRecipientTo(string email)
{
return AddRecipient(email, HowTo.MAPI_TO);
}
public bool AddRecipientCC(string email)
{
return AddRecipient(email, HowTo.MAPI_TO);
}
public bool AddRecipientBCC(string email)
{
return AddRecipient(email, HowTo.MAPI_TO);
}
public void AddAttachment(string strAttachmentFileName)
{
m_attachments.Add(strAttachmentFileName);
}
public int SendMailPopup(string strSubject, string strBody)
{
return SendMail(strSubject, strBody, MAPI_LOGON_UI | MAPI_DIALOG);
}
public int SendMailDirect(string strSubject, string strBody)
{
return SendMail(strSubject, strBody, MAPI_LOGON_UI);
}
[DllImport("MAPI32.DLL")]
static extern int MAPISendMail(IntPtr sess, IntPtr hwnd,
MapiMessage message, int flg, int rsv);
int SendMail(string strSubject, string strBody, int how)
{
MapiMessage msg = new MapiMessage();
msg.subject = strSubject;
msg.noteText = strBody;
msg.recips = GetRecipients(out msg.recipCount);
msg.files = GetAttachments(out msg.fileCount);
m_lastError = MAPISendMail(new IntPtr(0), new IntPtr(0), msg, how,
0);
if (m_lastError > 1)
MessageBox.Show("MAPISendMail failed! " + GetLastError(),
"MAPISendMail");
Cleanup(ref msg);
return m_lastError;
}
bool AddRecipient(string email, HowTo howTo)
{
MapiRecipDesc recipient = new MapiRecipDesc();
recipient.recipClass = (int)howTo;
recipient.name = email;
m_recipients.Add(recipient);
return true;
}
IntPtr GetRecipients(out int recipCount)
{
recipCount = 0;
if (m_recipients.Count == 0)
return IntPtr.Zero;
int size = Marshal.SizeOf(typeof(MapiRecipDesc));
IntPtr intPtr = Marshal.AllocHGlobal(m_recipients.Count * size);
int ptr = (int)intPtr;
foreach (MapiRecipDesc mapiDesc in m_recipients)
{
Marshal.StructureToPtr(mapiDesc, (IntPtr)ptr, false);
ptr += size;
}
recipCount = m_recipients.Count;
return intPtr;
}
IntPtr GetAttachments(out int fileCount)
{
fileCount = 0;
if (m_attachments == null)
return IntPtr.Zero;
if ((m_attachments.Count <= 0) || (m_attachments.Count >
maxAttachments))
return IntPtr.Zero;
int size = Marshal.SizeOf(typeof(MapiFileDesc));
IntPtr intPtr = Marshal.AllocHGlobal(m_attachments.Count * size);
MapiFileDesc mapiFileDesc = new MapiFileDesc();
mapiFileDesc.position = -1;
int ptr = (int)intPtr;
foreach (string strAttachment in m_attachments)
{
mapiFileDesc.name = Path.GetFileName(strAttachment);
mapiFileDesc.path = strAttachment;
Marshal.StructureToPtr(mapiFileDesc, (IntPtr)ptr, false);
ptr += size;
}
fileCount = m_attachments.Count;
return intPtr;
}
void Cleanup(ref MapiMessage msg)
{
int size = Marshal.SizeOf(typeof(MapiRecipDesc));
int ptr = 0;
if (msg.recips != IntPtr.Zero)
{
ptr = (int)msg.recips;
for (int i = 0; i < msg.recipCount; i++)
{
Marshal.DestroyStructure((IntPtr)ptr,
typeof(MapiRecipDesc));
ptr += size;
}
Marshal.FreeHGlobal(msg.recips);
}
if (msg.files != IntPtr.Zero)
{
size = Marshal.SizeOf(typeof(MapiFileDesc));
ptr = (int)msg.files;
for (int i = 0; i < msg.fileCount; i++)
{
Marshal.DestroyStructure((IntPtr)ptr,
typeof(MapiFileDesc));
ptr += size;
}
Marshal.FreeHGlobal(msg.files);
}
m_recipients.Clear();
m_attachments.Clear();
m_lastError = 0;
}
public string GetLastError()
{
if (m_lastError <= 26)
return errors[m_lastError];
return "MAPI error [" + m_lastError.ToString() + "]";
}
readonly string[] errors = 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]"
};
List<MapiRecipDesc> m_recipients = new
List<MapiRecipDesc>();
List<string> m_attachments = new List<string>();
int m_lastError = 0;
const int MAPI_LOGON_UI = 0x00000001;
const int MAPI_DIALOG = 0x00000008;
const int maxAttachments = 20;
enum HowTo { MAPI_ORIG = 0, MAPI_TO, MAPI_CC, MAPI_BCC };
}
[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;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiRecipDesc
{
public int reserved;
public int recipClass;
public string name;
public string address;
public int eIDSize;
public IntPtr entryID;
}
Utilisez la classe MAPI
comme ci-dessous.
MAPI mapi = new MAPI();
mapi.AddAttachment("c:\\temp\\file1.txt");
mapi.AddAttachment("c:\\temp\\file2.txt");
mapi.AddRecipientTo("[email protected]");
mapi.AddRecipientTo("[email protected]");
mapi.SendMailPopup("testing", "body text");
// Or if you want try and do a direct send without displaying the
// mail dialog mapi.SendMailDirect("testing", "body text");
Référence: Projet de code