2015-04-17 119 views
0

我需要通过IIS创建一个outlook .msg文件,它可以当我在“IIS Express”中运行它,但无法在IIS中运行甚至将应用程序池设置为本地系统。ASP.NET无法调用Outlook功能来创建.msg文件

错误消息:操作中止(从HRESULT异常:0x80004004(E_ABORT))在Microsoft.Office.Interop.Outlook.Attachments.Add(对象源,对象类型,对象的位置,对象显示名称)

环境: Win7的32位,Office 2010中,Vistual Studio Pro中2013

的源代码如下:

Try 
     Dim oApp As Interop.Outlook._Application 
     Dim oMsg As Interop.Outlook._MailItem 
     oApp = New Interop.Outlook.Application 
     oMsg = oApp.CreateItem(Interop.Outlook.OlItemType.olMailItem) 
     oMsg.Subject = "Test Subject" 
     oMsg.Body = "Test Body" 
     oMsg.To = "" 

     Dim attachedFilePath As String = "C:\\temp\\A1234563A.zip" 
     If String.IsNullOrEmpty(attachedFilePath) = False Then 
      Dim sBodyLen As Integer = Int(oMsg.Body) 
      Dim oAttachs As Interop.Outlook.Attachments = oMsg.Attachments 
      Dim oAttach As Interop.Outlook.Attachment 
      oAttach = oAttachs.Add(attachedFilePath, , sBodyLen, "A1234563A.zip") 
     End If 
     oMsg.SaveAs("c:\\temp\\abcd.msg", Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG) 

    Catch ex As System.Exception 
     'xxxxx 
    Finally 
     GC.Collect() 
     GC.WaitForPendingFinalizers() 
    End Try 
+2

对不起,但您无法从Web服务器访问客户端Outlook实例,因为Web服务器通常在单独的计算机上运行。您需要直接访问Exchange Server。 –

+0

尤尔根有权利。如果你想为你的客户创建一个.msg,你不能这样做。在IISExpress上,它可以工作,因为它是您的机器和客户端。如果要在IIS服务器上创建该文件,则必须在其上安装Outlook,在服务器上创建.msg文件以读取该文件并将其回复给客户端。但出于安全考虑,您将无法在Web服务器上安装Outlook,并在Web服务器上创建文件来读取它并将其回复给您的客户端显然不是一个干净的解决方案^^。 – D4rkTiger

回答

2

微软目前并不提倡,不支持,Microsoft Office应用程序fr的自动化om在任何无人参与的非交互式客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT服务)中,因为Office在此环境中运行时可能会出现不稳定的行为和/或死锁。

如果您正在构建一个在服务器端上下文中运行的解决方案,那么您应该尝试使用对于无人执行安全的组件。或者,您应该尝试找到允许至少部分代码运行客户端的替代方案。如果您从服务器端解决方案使用Office应用程序,则该应用程序将缺少成功运行所需的许多必要功能。此外,您将面临整体解决方案稳定性的风险。

阅读更多关于Considerations for server-side Automation of Office文章。

+0

谢谢,现在我创建.msg文件没有Outlook。它似乎有用。 –

0

我使用System.Net.Mail代替 - https://msdn.microsoft.com/en-us/library/system.net.mail(v=vs.110).aspx

你建立一个MAILMESSAGE,您可以添加附件,并设置重要性,并做你上面做的一切。

这对我来说很好,你不需要在服务器上安装任何东西。

编辑

下面是一些对你的示例代码 - 导入System.Net.MailSystem.Configuration命名空间。在这个例子中,我发送一个日志,所以我从App.Config获得地址和SMTP中继。您可以根据需要更改这些设置。

这也从App.Config中指定的位置附加文件。

string[] recipients = ConfigurationManager.AppSettings["recipients"].ToString().Split(','); 


      MailMessage msg = new MailMessage(); 
      msg.From = new MailAddress("[email protected]"); 
      msg.Subject = "Log Error Report"; 

      foreach (string addr in recipients) 
      { 
       msg.To.Add(new MailAddress(addr)); 
      } 

      string body = System.Environment.NewLine + "Please check these logs for errors."; 
      body += System.Environment.NewLine + "Message line 2"; 

      msg.Body = body; 
      msg.Priority = MailPriority.High; 

      String attchMnts = ConfigurationManager.AppSettings["logfile"].ToString(); 
      String[] attchPaths = attchMnts.Split(','); 

      foreach (string path in attchPaths) 
      { 
       Attachment atch = new Attachment(path); 
       msg.Attachments.Add(atch); 
      } 

      SmtpClient client = new SmtpClient(ConfigurationManager.AppSettings["smtpRelay"].ToString()); 
      client.Send(msg); 
+0

谢谢,我需要添加附件并保存为用户的.msg文件。 –

+0

System.Net.Mail支持附件。我已经用日志文件完成了。我会更新我的帖子,为您添加一个样本。 – Tim

1

您的选项是

  1. 扩展MAPI(OpenImsgOnIStg等)来创建一个MSG文件,并设置所有相关的MAPI属性,但它是从C只能访问++或Delphi

  2. 使用Windows API在代码中明确构建文件(它的格式已记录) - https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx

  3. 使用Redemption - 这是一个扩展的MAPI包装器,可以从任何语言的服务中使用,包括C#,VB。Net或VB脚本:

 


     set Session = CreateObject("Redemption.RDOSession") 
     set Msg = Session.CreateMessageFromMsgFile("C:\Temp\test.msg") 
     Msg.Sent = true 
     set recip = Msg.Recipients.AddEx("This user", "[email protected]", "SMTP", olTo) 
     Msg.Subject = "fake received message" 
     Msg.Body = "just a test" 
     Msg.SentOn = Now 
     Msg.ReceivedTime = Now 
     'set the sender related properties 
     vSenderEntryId = Session.CreateOneOffEntryID("Joe The Sender", "SMTP", "[email protected]", false, true) 
     'PR_SENDER_xyz 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1E001F") = "SMTP" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1F001F") = "[email protected]" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C190102") = vSenderEntryId 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1A001F") = "Joe The Sender" 
     'PR_SENT_REPRESENTING_xyz 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0064001F") = "SMTP" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0065001F") = "[email protected]" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x00410102") = vSenderEntryId 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0042001F") = "Joe The Sender" 
     'all done 
     Msg.Save 

 
+0

谢谢,现在我创建.msg文件没有Outlook。它似乎有用。 –

+0

@chenshuguang,你用什么方法创建msg文件? – par

1

感谢所有,最后我做到这一点如下:1. 手动创建由Outlook模板.msg文件。 2.打开它并复制到新的流。来自intenet的许多代码。 3.将我的信息更新到此流,并保存为新的.msg文件。 (以下是我更新.msg文件中的附件文件时的源代码,并且您应该从OutlookStorage.cs中获取其他源代码)。

//create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store 
NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out memoryStorageBytes); 
        NativeMethods.StgCreateDocfileOnILockBytes(memoryStorageBytes, NativeMethods.STGM.CREATE | NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, out memoryStorage); 

//copy the save storage into the new storage 
saveMsg.storage.CopyTo(0, null, IntPtr.Zero, memoryStorage); 

//Attachments (37xx): 
//0x3701: Attachment data  <- This is the binary attachment 
//0x3703: Attach extension 
//0x3704: Attach filename 
//0x3707: Attach long filenm 
//0x370E: Attach mime tag 
//0x3712: Attach ID (?) 

// replace attachment with myself file 
var myNameIdSourceStorage = memoryStorage.OpenStorage(OutlookStorage.ATTACH_STORAGE_PREFIX + "00000000", IntPtr.Zero, NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE,IntPtr.Zero, 0); 
            myNameIdSourceStorage.DestroyElement("__substg1.0_37010102"); 

// Create the property stream again and write in the padded version 
var pStream = myNameIdSourceStorage.CreateStream("__substg1.0_37010102", 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, 0); 
pStream.Write(newFileByte, newFileByte.Length, IntPtr.Zero); 

// Open stream from the storage 
var mystream = myNameIdSourceStorage.OpenStream("__properties_version1.0", IntPtr.Zero, 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0); 

System.Runtime.InteropServices.ComTypes.STATSTG elementStats; 
mystream.Stat(out elementStats, 0);      

// Read the stream into a managed byte array 
var iStreamContent = new byte[elementStats.cbSize]; 
mystream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero); 
iStreamContent[0xc0] = (byte)(newFileByte.Length & 0xFF); 
iStreamContent[0xc1] = (byte)(newFileByte.Length >> 8); 
iStreamContent[0xc2] = (byte)(newFileByte.Length >> 16); 
iStreamContent[0xc3] = (byte)(newFileByte.Length >> 24); 
mystream.Write(iStreamContent, 0, IntPtr.Zero); 

//0x3704: Attach filename 
myNameIdSourceStorage.DestroyElement("__substg1.0_3704001F"); 
pStream = myNameIdSourceStorage.CreateStream("__substg1.0_3704001F", 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, 0); 
pStream.Write(newProps, 8, IntPtr.Zero);