我正在寻找一种方法来打开用户的默认电子邮件程序以编写新电子邮件并从 C# 应用程序中指定附件。现在,我可以开始发送电子邮件并指定收件人、主题、正文等,但我找不到任何方法来同时指定附件。
System.Diagnostics.Process.Start(@"mailto:me@mydomain.com&subject=Hi&body=%0D%0DSent from my Kinect");
这对于基本的电子邮件来说效果很好,但无法添加附件。作为背景知识,我的老板想使用语音命令从 Kinect 获取快照,然后通过电子邮件将其发送给某人。
通过“标题相似的问题”,我找到了this ,这可能是错误的语言,但它让我觉得至少有一种方法可以用 Microsoft Outlook 做到这一点。这是我工作中的大多数人使用的,但我真的希望有一些可以与任何邮件客户端一起使用的东西。
我不想只通过 C# 发送电子邮件,因为我希望用户能够在发送之前在他们的邮件客户端中编辑电子邮件。
那么,问题来了:有没有办法在打开用户的默认电子邮件程序时指定附件?如果没有,我在哪里可以找到有关使用 C# 在 Microsoft Outlook 中创建带有附件的电子邮件的资源?
最佳答案
我已经使用了代码 here打开带有附件的用户默认电子邮件客户端。
// Below is the source code and simple test class for creating and displaying emails.
// It uses the MAPI API and is therefore not subject to the same restrictions as
// the "mailto" shell extension.
//
// Using the MapiMailMessage you can set the title, subject, recipients and attach files.
// Then show the resulting email to the user, ready from them to send. This class is very
// useful for supporting applications and enriching addins.
//
// Note, that the class is a port from a VB version I had and although it does have
// comments, it is not up to my usual standard. I will be revisiting this and tidying
// it up shortly.
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
#region Test Class
public class TestMapiMessageClass
{
/// <summary>
/// Test method to create and show an email
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
MapiMailMessage message = new MapiMailMessage("Test Message", "Test Body");
message.Recipients.Add("Test@Test.com");
message.Files.Add(@"C:\del.txt");
message.ShowDialog();
Console.ReadLine();
}
}
#endregion Test Class
#region Public MapiMailMessage Class
/// <summary>
/// Represents an email message to be sent through MAPI.
/// </summary>
public class MapiMailMessage
{
#region Private MapiFileDescriptor Class
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private class MapiFileDescriptor
{
public int reserved = 0;
public int flags = 0;
public int position = 0;
public string path = null;
public string name = null;
public IntPtr type = IntPtr.Zero;
}
#endregion Private MapiFileDescriptor Class
#region Enums
/// <summary>
/// Specifies the valid RecipientTypes for a Recipient.
/// </summary>
public enum RecipientType : int
{
/// <summary>
/// Recipient will be in the TO list.
/// </summary>
To = 1,
/// <summary>
/// Recipient will be in the CC list.
/// </summary>
CC = 2,
/// <summary>
/// Recipient will be in the BCC list.
/// </summary>
BCC = 3
};
#endregion Enums
#region Member Variables
private string _subject;
private string _body;
private RecipientCollection _recipientCollection;
private ArrayList _files;
private ManualResetEvent _manualResetEvent;
#endregion Member Variables
#region Constructors
/// <summary>
/// Creates a blank mail message.
/// </summary>
public MapiMailMessage()
{
_files = new ArrayList();
_recipientCollection = new RecipientCollection();
_manualResetEvent = new ManualResetEvent(false);
}
/// <summary>
/// Creates a new mail message with the specified subject.
/// </summary>
public MapiMailMessage(string subject)
: this()
{
_subject = subject;
}
/// <summary>
/// Creates a new mail message with the specified subject and body.
/// </summary>
public MapiMailMessage(string subject, string body)
: this()
{
_subject = subject;
_body = body;
}
#endregion Constructors
#region Public Properties
/// <summary>
/// Gets or sets the subject of this mail message.
/// </summary>
public string Subject
{
get { return _subject; }
set { _subject = value; }
}
/// <summary>
/// Gets or sets the body of this mail message.
/// </summary>
public string Body
{
get { return _body; }
set { _body = value; }
}
/// <summary>
/// Gets the recipient list for this mail message.
/// </summary>
public RecipientCollection Recipients
{
get { return _recipientCollection; }
}
/// <summary>
/// Gets the file list for this mail message.
/// </summary>
public ArrayList Files
{
get { return _files; }
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Displays the mail message dialog asynchronously.
/// </summary>
public void ShowDialog()
{
// Create the mail message in an STA thread
Thread t = new Thread(new ThreadStart(_ShowMail));
t.IsBackground = true;
t.ApartmentState = ApartmentState.STA;
t.Start();
// only return when the new thread has built it's interop representation
_manualResetEvent.WaitOne();
_manualResetEvent.Reset();
}
#endregion Public Methods
#region Private Methods
/// <summary>
/// Sends the mail message.
/// </summary>
private void _ShowMail(object ignore)
{
MAPIHelperInterop.MapiMessage message = new MAPIHelperInterop.MapiMessage();
using (RecipientCollection.InteropRecipientCollection interopRecipients
= _recipientCollection.GetInteropRepresentation())
{
message.Subject = _subject;
message.NoteText = _body;
message.Recipients = interopRecipients.Handle;
message.RecipientCount = _recipientCollection.Count;
// Check if we need to add attachments
if (_files.Count > 0)
{
// Add attachments
message.Files = _AllocAttachments(out message.FileCount);
}
// Signal the creating thread (make the remaining code async)
_manualResetEvent.Set();
const int MAPI_DIALOG = 0x8;
//const int MAPI_LOGON_UI = 0x1;
const int SUCCESS_SUCCESS = 0;
int error = MAPIHelperInterop.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_DIALOG, 0);
if (_files.Count > 0)
{
// Deallocate the files
_DeallocFiles(message);
}
// Check for error
if (error != SUCCESS_SUCCESS)
{
_LogErrorMapi(error);
}
}
}
/// <summary>
/// Deallocates the files in a message.
/// </summary>
/// <param name="message">The message to deallocate the files from.</param>
private void _DeallocFiles(MAPIHelperInterop.MapiMessage message)
{
if (message.Files != IntPtr.Zero)
{
Type fileDescType = typeof(MapiFileDescriptor);
int fsize = Marshal.SizeOf(fileDescType);
// Get the ptr to the files
int runptr = (int)message.Files;
// Release each file
for (int i = 0; i < message.FileCount; i++)
{
Marshal.DestroyStructure((IntPtr)runptr, fileDescType);
runptr += fsize;
}
// Release the file
Marshal.FreeHGlobal(message.Files);
}
}
/// <summary>
/// Allocates the file attachments
/// </summary>
/// <param name="fileCount"></param>
/// <returns></returns>
private IntPtr _AllocAttachments(out int fileCount)
{
fileCount = 0;
if (_files == null)
{
return IntPtr.Zero;
}
if ((_files.Count <= 0) || (_files.Count > 100))
{
return IntPtr.Zero;
}
Type atype = typeof(MapiFileDescriptor);
int asize = Marshal.SizeOf(atype);
IntPtr ptra = Marshal.AllocHGlobal(_files.Count * asize);
MapiFileDescriptor mfd = new MapiFileDescriptor();
mfd.position = -1;
int runptr = (int)ptra;
for (int i = 0; i < _files.Count; i++)
{
string path = _files[i] as string;
mfd.name = Path.GetFileName(path);
mfd.path = path;
Marshal.StructureToPtr(mfd, (IntPtr)runptr, false);
runptr += asize;
}
fileCount = _files.Count;
return ptra;
}
/// <summary>
/// Sends the mail message.
/// </summary>
private void _ShowMail()
{
_ShowMail(null);
}
/// <summary>
/// Logs any Mapi errors.
/// </summary>
private void _LogErrorMapi(int errorCode)
{
const int MAPI_USER_ABORT = 1;
const int MAPI_E_FAILURE = 2;
const int MAPI_E_LOGIN_FAILURE = 3;
const int MAPI_E_DISK_FULL = 4;
const int MAPI_E_INSUFFICIENT_MEMORY = 5;
const int MAPI_E_BLK_TOO_SMALL = 6;
const int MAPI_E_TOO_MANY_SESSIONS = 8;
const int MAPI_E_TOO_MANY_FILES = 9;
const int MAPI_E_TOO_MANY_RECIPIENTS = 10;
const int MAPI_E_ATTACHMENT_NOT_FOUND = 11;
const int MAPI_E_ATTACHMENT_OPEN_FAILURE = 12;
const int MAPI_E_ATTACHMENT_WRITE_FAILURE = 13;
const int MAPI_E_UNKNOWN_RECIPIENT = 14;
const int MAPI_E_BAD_RECIPTYPE = 15;
const int MAPI_E_NO_MESSAGES = 16;
const int MAPI_E_INVALID_MESSAGE = 17;
const int MAPI_E_TEXT_TOO_LARGE = 18;
const int MAPI_E_INVALID_SESSION = 19;
const int MAPI_E_TYPE_NOT_SUPPORTED = 20;
const int MAPI_E_AMBIGUOUS_RECIPIENT = 21;
const int MAPI_E_MESSAGE_IN_USE = 22;
const int MAPI_E_NETWORK_FAILURE = 23;
const int MAPI_E_INVALID_EDITFIELDS = 24;
const int MAPI_E_INVALID_RECIPS = 25;
const int MAPI_E_NOT_SUPPORTED = 26;
const int MAPI_E_NO_LIBRARY = 999;
const int MAPI_E_INVALID_PARAMETER = 998;
string error = string.Empty;
switch (errorCode)
{
case MAPI_USER_ABORT:
error = "User Aborted.";
break;
case MAPI_E_FAILURE:
error = "MAPI Failure.";
break;
case MAPI_E_LOGIN_FAILURE:
error = "Login Failure.";
break;
case MAPI_E_DISK_FULL:
error = "MAPI Disk full.";
break;
case MAPI_E_INSUFFICIENT_MEMORY:
error = "MAPI Insufficient memory.";
break;
case MAPI_E_BLK_TOO_SMALL:
error = "MAPI Block too small.";
break;
case MAPI_E_TOO_MANY_SESSIONS:
error = "MAPI Too many sessions.";
break;
case MAPI_E_TOO_MANY_FILES:
error = "MAPI too many files.";
break;
case MAPI_E_TOO_MANY_RECIPIENTS:
error = "MAPI too many recipients.";
break;
case MAPI_E_ATTACHMENT_NOT_FOUND:
error = "MAPI Attachment not found.";
break;
case MAPI_E_ATTACHMENT_OPEN_FAILURE:
error = "MAPI Attachment open failure.";
break;
case MAPI_E_ATTACHMENT_WRITE_FAILURE:
error = "MAPI Attachment Write Failure.";
break;
case MAPI_E_UNKNOWN_RECIPIENT:
error = "MAPI Unknown recipient.";
break;
case MAPI_E_BAD_RECIPTYPE:
error = "MAPI Bad recipient type.";
break;
case MAPI_E_NO_MESSAGES:
error = "MAPI No messages.";
break;
case MAPI_E_INVALID_MESSAGE:
error = "MAPI Invalid message.";
break;
case MAPI_E_TEXT_TOO_LARGE:
error = "MAPI Text too large.";
break;
case MAPI_E_INVALID_SESSION:
error = "MAPI Invalid session.";
break;
case MAPI_E_TYPE_NOT_SUPPORTED:
error = "MAPI Type not supported.";
break;
case MAPI_E_AMBIGUOUS_RECIPIENT:
error = "MAPI Ambiguous recipient.";
break;
case MAPI_E_MESSAGE_IN_USE:
error = "MAPI Message in use.";
break;
case MAPI_E_NETWORK_FAILURE:
error = "MAPI Network failure.";
break;
case MAPI_E_INVALID_EDITFIELDS:
error = "MAPI Invalid edit fields.";
break;
case MAPI_E_INVALID_RECIPS:
error = "MAPI Invalid Recipients.";
break;
case MAPI_E_NOT_SUPPORTED:
error = "MAPI Not supported.";
break;
case MAPI_E_NO_LIBRARY:
error = "MAPI No Library.";
break;
case MAPI_E_INVALID_PARAMETER:
error = "MAPI Invalid parameter.";
break;
}
Debug.WriteLine("Error sending MAPI Email. Error: " + error + " (code = " + errorCode + ").");
}
#endregion Private Methods
#region Private MAPIHelperInterop Class
/// <summary>
/// Internal class for calling MAPI APIs
/// </summary>
internal class MAPIHelperInterop
{
#region Constructors
/// <summary>
/// Private constructor.
/// </summary>
private MAPIHelperInterop()
{
// Intenationally blank
}
#endregion Constructors
#region Constants
public const int MAPI_LOGON_UI = 0x1;
#endregion Constants
#region APIs
[DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)]
public static extern int MAPILogon(IntPtr hwnd, string prf, string pw, int flg, int rsv, ref IntPtr sess);
#endregion APIs
#region Structs
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiMessage
{
public int Reserved = 0;
public string Subject = null;
public string NoteText = null;
public string MessageType = null;
public string DateReceived = null;
public string ConversationID = null;
public int Flags = 0;
public IntPtr Originator = IntPtr.Zero;
public int RecipientCount = 0;
public IntPtr Recipients = IntPtr.Zero;
public int FileCount = 0;
public IntPtr Files = IntPtr.Zero;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class MapiRecipDesc
{
public int Reserved = 0;
public int RecipientClass = 0;
public string Name = null;
public string Address = null;
public int eIDSize = 0;
public IntPtr EntryID = IntPtr.Zero;
}
[DllImport("MAPI32.DLL")]
public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv);
#endregion Structs
}
#endregion Private MAPIHelperInterop Class
}
#endregion Public MapiMailMessage Class
#region Public Recipient Class
/// <summary>
/// Represents a Recipient for a MapiMailMessage.
/// </summary>
public class Recipient
{
#region Public Properties
/// <summary>
/// The email address of this recipient.
/// </summary>
public string Address = null;
/// <summary>
/// The display name of this recipient.
/// </summary>
public string DisplayName = null;
/// <summary>
/// How the recipient will receive this message (To, CC, BCC).
/// </summary>
public MapiMailMessage.RecipientType RecipientType = MapiMailMessage.RecipientType.To;
#endregion Public Properties
#region Constructors
/// <summary>
/// Creates a new recipient with the specified address.
/// </summary>
public Recipient(string address)
{
Address = address;
}
/// <summary>
/// Creates a new recipient with the specified address and display name.
/// </summary>
public Recipient(string address, string displayName)
{
Address = address;
DisplayName = displayName;
}
/// <summary>
/// Creates a new recipient with the specified address and recipient type.
/// </summary>
public Recipient(string address, MapiMailMessage.RecipientType recipientType)
{
Address = address;
RecipientType = recipientType;
}
/// <summary>
/// Creates a new recipient with the specified address, display name and recipient type.
/// </summary>
public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType)
{
Address = address;
DisplayName = displayName;
RecipientType = recipientType;
}
#endregion Constructors
#region Internal Methods
/// <summary>
/// Returns an interop representation of a recepient.
/// </summary>
/// <returns></returns>
internal MapiMailMessage.MAPIHelperInterop.MapiRecipDesc GetInteropRepresentation()
{
MapiMailMessage.MAPIHelperInterop.MapiRecipDesc interop = new MapiMailMessage.MAPIHelperInterop.MapiRecipDesc();
if (DisplayName == null)
{
interop.Name = Address;
}
else
{
interop.Name = DisplayName;
interop.Address = Address;
}
interop.RecipientClass = (int)RecipientType;
return interop;
}
#endregion Internal Methods
}
#endregion Public Recipient Class
#region Public RecipientCollection Class
/// <summary>
/// Represents a colleciton of recipients for a mail message.
/// </summary>
public class RecipientCollection : CollectionBase
{
/// <summary>
/// Adds the specified recipient to this collection.
/// </summary>
public void Add(Recipient value)
{
List.Add(value);
}
/// <summary>
/// Adds a new recipient with the specified address to this collection.
/// </summary>
public void Add(string address)
{
this.Add(new Recipient(address));
}
/// <summary>
/// Adds a new recipient with the specified address and display name to this collection.
/// </summary>
public void Add(string address, string displayName)
{
this.Add(new Recipient(address, displayName));
}
/// <summary>
/// Adds a new recipient with the specified address and recipient type to this collection.
/// </summary>
public void Add(string address, MapiMailMessage.RecipientType recipientType)
{
this.Add(new Recipient(address, recipientType));
}
/// <summary>
/// Adds a new recipient with the specified address, display name and recipient type to this collection.
/// </summary>
public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType)
{
this.Add(new Recipient(address, displayName, recipientType));
}
/// <summary>
/// Returns the recipient stored in this collection at the specified index.
/// </summary>
public Recipient this[int index]
{
get
{
return (Recipient)List[index];
}
}
internal InteropRecipientCollection GetInteropRepresentation()
{
return new InteropRecipientCollection(this);
}
/// <summary>
/// Struct which contains an interop representation of a colleciton of recipients.
/// </summary>
internal struct InteropRecipientCollection : IDisposable
{
#region Member Variables
private IntPtr _handle;
private int _count;
#endregion Member Variables
#region Constructors
/// <summary>
/// Default constructor for creating InteropRecipientCollection.
/// </summary>
/// <param name="outer"></param>
public InteropRecipientCollection(RecipientCollection outer)
{
_count = outer.Count;
if (_count == 0)
{
_handle = IntPtr.Zero;
return;
}
// allocate enough memory to hold all recipients
int size = Marshal.SizeOf(typeof(MapiMailMessage.MAPIHelperInterop.MapiRecipDesc));
_handle = Marshal.AllocHGlobal(_count * size);
// place all interop recipients into the memory just allocated
int ptr = (int)_handle;
foreach (Recipient native in outer)
{
MapiMailMessage.MAPIHelperInterop.MapiRecipDesc interop = native.GetInteropRepresentation();
// stick it in the memory block
Marshal.StructureToPtr(interop, (IntPtr)ptr, false);
ptr += size;
}
}
#endregion Costructors
#region Public Properties
public IntPtr Handle
{
get { return _handle; }
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Disposes of resources.
/// </summary>
public void Dispose()
{
if (_handle != IntPtr.Zero)
{
Type type = typeof(MapiMailMessage.MAPIHelperInterop.MapiRecipDesc);
int size = Marshal.SizeOf(type);
// destroy all the structures in the memory area
int ptr = (int)_handle;
for (int i = 0; i < _count; i++)
{
Marshal.DestroyStructure((IntPtr)ptr, type);
ptr += size;
}
// free the memory
Marshal.FreeHGlobal(_handle);
_handle = IntPtr.Zero;
_count = 0;
}
}
#endregion Public Methods
}
}
#endregion Public RecipientCollection Class
关于c# - 打开带附件的默认电子邮件程序 (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6753008/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R