I need create a outlook .msg file by IIS, it is ok when I run it in "IIS Express", but can not run in IIS even set applicationpool to LocalSystem.
Error message:Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT)) at Microsoft.Office.Interop.Outlook.Attachments.Add(Object Source, Object Type, Object Position, Object DisplayName)
Environment: Win7 32bit, Office 2010, Vistual Studio Pro 2013
Source code as following:
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
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.
Read more about that in the Considerations for server-side Automation of Office article.
Thanks All, At last I do it as following:
1. Create a template .msg file by outlook manually.
2. Open it and copy to a new stream. Many code for this from intenet.
3. Update my information to this stream, and save as a new .msg file. (Following is source when I update attachment file in .msg file, and you should get other source from 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);
Your options are
Extended MAPI (OpenImsgOnIStg etc.) to create an MSG file and set all the relevant MAPI properties, but it is only accessible from the C++ or Delphi
Use Windows API to build the file explicitly in your code (its format is documented) - https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx
Use Redemption (I am its author) - it is an Extended MAPI wrapper that can be used from a service in any language including C#, VB.Net or VB script:
set Session = CreateObject("Redemption.RDOSession")
set Msg = Session.CreateMessageFromMsgFile("C:\Temp\test.msg")
Msg.Sent = true
set recip = Msg.Recipients.AddEx("This user", "this.user#domain.demo", "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", "joe#domain.demo", false, true)
'PR_SENDER_xyz
Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1E001F") = "SMTP"
Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1F001F") = "joe#domain.demo"
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") = "joe#domain.demo"
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
I use System.Net.Mail instead - https://msdn.microsoft.com/en-us/library/system.net.mail(v=vs.110).aspx
You set up a MailMessage, you can add attachments and set importance, and do everything you're doing above.
This works very well for me, and you don't need to install anything on the server.
EDIT
Here's some sample code for you - import the System.Net.Mail and System.Configuration namespaces. In this example, I'm sending a log, so I get the to addresses and SMTP relay from App.Config. You can change these for what you need.
This also attaches a file from a location also specified in App.Config.
string[] recipients = ConfigurationManager.AppSettings["recipients"].ToString().Split(',');
MailMessage msg = new MailMessage();
msg.From = new MailAddress("noreply#somewhere.com");
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);
Outlook Object Model cannot be used from a service (including IIS). Your options are:
Use Extended MAPI (OpenIMsgOnIStg etc.) to create an MSG file and set all the relevant MAPI properties, but it is only accessible from the C++ or Delphi. Note the Outlook must be installed for the Extended MAPI system to be present. Since MAPI system is loaded in-proc, the bitnes of your code must match that of Outlook/MAPI.
Use Windows API to build the file explicitly in your code (it's format is documented) - https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx
Use Redemption (I am its author) - it is an Extended MAPI wrapper that can be used from a service in any language including C#, VB.Net or VB script:
set Session = CreateObject("Redemption.RDOSession")
set Msg = Session.CreateMessageFromMsgFile("C:\Temp\test.msg")
Msg.Sent = true
set recip = Msg.Recipients.AddEx("This user", "this.user#domain.demo", "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", "joe#domain.demo", false, true)
'PR_SENDER_xyz
Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1E001F") = "SMTP"
Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1F001F") = "joe#domain.demo"
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") = "joe#domain.demo"
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
I use asp classic to authenticate a user with LDAP. There are about 10 000 accounts in the LDAP and the check for authentication in asp is quite slow (15 seconds).
I used on the same server the LDP tool (from Microsoft) and everything (from connection, binding and search) is fast.
Here's my code, I tried 3 different options and I had same results :
Using SQL instructions :
Dim oConn: Set oConn = Server.CreateObject("ADODB.Connection")
oConn.Provider = "ADsDSOOBJECT"
oConn.Properties("User ID") = Username
oConn.Properties("Password") = Password
oConn.Properties("Encrypt Password") = True
oConn.Open "DS Query", Username, Password
Dim Query: Query = "SELECT sAMAccountName FROM 'LDAP://ldap.mydomain.com/CN=" & Username & ",CN=Users' WHERE objectCategory = 'person' AND objectClass='user' AND SAMAccountName = '" & Username & "' "
Dim oCmd: Set oCmd = Server.CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
oCmd.CommandText = Query
Dim oRs: Set oRS = oCmd.Execute
If oRS.BOF Or oRS.EOF Then
' Authentication failed
Else
' Autentication passed
End If
...
Using LDAP instructions :
Dim oConn: Set oConn = Server.CreateObject("ADODB.Connection")
oConn.Provider = "ADsDSOOBJECT"
oConn.Properties("User ID") = Username
oConn.Properties("Password") = Password
oConn.Properties("Encrypt Password") = True
oConn.Open "DS Query", Username, Password
Dim Query: Query = "<LDAP://ldap.mydomain.com>;(samAccountName=" & Username & ");samAccountName;subtree"
Dim oCmd: Set oCmd = Server.CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
oCmd.CommandText = Query
Dim oRs: Set oRS = oCmd.Execute
If oRS.BOF Or oRS.EOF Then
' Authentication failed
Else
' Autentication passed
End If
...
Using IADS objects :
Dim DSODomaine
Dim DSOContainer
On Error Resume Next
Set DSODomaine = GetObject("LDAP:")
Set DSOContainer = DSODomaine.OpenDSObject("LDAP://ldap.mydomain.com", Username, Password, ADS_SECURE_AUTHENTICATION + ADS_SERVER_BIND)
If Err.Number <> 0 Then
' Authentication failed
Else
' Autentication passed
End If
...
The 3 examples are all slow. What could I do to improve performance using asp classic ?
Ancient thread, but you can include the port in the address like
LDAP://ldap.mydomain.com:389 - that should speed up your query
Later edit - if your issue is exactly 15 seconds delay, this will help:
Windows tries to retrieve a fresh CRL (certificate revocation list) from both its own and third-party servers. This looks like it times out in exactly 15 seconds. This might be the case if the machine is isolated or doesn’t have internet access to those resources (blocked/firewall, slow connection etc).
If your CA/Certificate is already available on the webserver you try to lower the timeout to see if it solves the issue?
We just need to follow these steps on Vault Server:
Start gpedit.msc -> Local Computer policy -> Computer Configuration -> Administrative Templates -> System -> Internet Communication Management -> Internet Communication Settings -> Turn off automatic root certificate update = Enabled
Start gpedit.msc -> Local Computer policy -> Computer Configuration -> Windows Settings -> Security Settings -> Public Key Policy -> Certificate Path Validation Path. Select tab “Network Retrieval” and enable the “Define these policy settings”. Deselect “Automatic update root….” And most important set the timeout values to 1.
I'm developing web pages using Razor C# language in WebMatrix. I have a hosted website, I'm trying to incorporate an email system into it.
As per this article on WebMail I have set up the WebMail settings in my _AppStart.cshtml page. I've got my settings from my service provider. He's provided me a sample code using CDO object:
dim config, sch
set config = CreateObject("CDO.Configuration")
sch = "http://schemas.microsoft.com/cdo/configuration/"
with config.Fields
.item(sch & "sendusing") = 2 ' cdoSendUsingPort
.item(sch & "smtpserver") = "myserver"
.item(sch & "smtpserverport") = 25
.item(sch & "smtpusessl") = False
.item(sch & "smtpconnectiontimeout") = 60
.item(sch & "smtpauthenticate") = 1 'basic auth
.item(sch & "sendusername") = "myemail#email.com"
.item(sch & "sendpassword") = "password"
.update
end with
Set myMail=CreateObject("CDO.Message")
With myMail
.Configuration = config
.Subject = Request.Form("txtSubject")
.From = Request.Form("txtFrom")
.To = Request.Form("txtTo")
.TextBody = Request.Form("txtMessage")
Call .Send()
End With
As you can see the above code is made in CDO. I'm trying to use the WebMail in Razor. The only point where I'm stuck is that my email server is not SSL but requires basic auth. I can't find any authentication setting in WebMail. How do I set the SMTP authentication in WebMail? This is my current code:
WebMail.SmtpServer = "myserver";
WebMail.SmtpPort = 25;
WebMail.EnableSsl = false;
WebMail.UserName = "myemail#email.com";
WebMail.Password = "password";
WebMail.From = "Support <myemail#email.com>";
Thanks in advance!
Basic authentication with mail servers usually consists of providing a user name and password. You set those using the WebMail.UserName and WebMail.Password properties.
By the way, your provider has given you sample code for sending mail using CDO in classic ASP. It is of no use to you.
Here's a basic example in c#. The Smtp class takes username password.
MailMessage mail = new MailMessage("emailfrom","emailto");
mail.From = new MailAddress("emailfrom");
mail.Subject = txtsbjct.Text;
string Body = txtmsg.Text;
mail.Body = Body;
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "localhost";
smtp.Credentials = new System.Net.NetworkCredential
("youremail", "yourpassword");
I am sick and tired of my hosting company. I think you can help me here.
I have simple need that I have my complete website written in Classic ASP. Now I want to have a page which sends email using CDOSYS. I wanted to have that script in ASP from my hosting company that what setting should i have. They always send me code in C#.
here is they send always:
CDOSYS is part of the System.Web.Mail namespace and is installed by default on Windows 2000 and Windows XP platforms. It replaces CDONTS for sending SMTP email messages and can be used with our IIS 6 and IIS 7 Windows hosting accounts. The following code sample demonstrates how to create, format, and send email.
private void SendEmail()
{
const string SERVER = "relay-hosting.secureserver.net";
MailMessage oMail = new System.Web.Mail.MailMessage();
oMail.From = "emailaddress#domainname";
oMail.To = "emailaddress#domainname";
oMail.Subject = "Test email subject";
oMail.BodyFormat = MailFormat.Html; // enumeration
oMail.Priority = MailPriority.High; // enumeration
oMail.Body = "Sent at: " + DateTime.Now;
SmtpMail.SmtpServer = SERVER;
SmtpMail.Send(oMail);
oMail = null; // free up resources
}
Here is my ASP which I written to use same thing but doesn't work:
Set objCDOSYSMail = Server.CreateObject("CDO.Message")
Set objCDOSYSCon = Server.CreateObject ("CDO.Configuration")
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "relay-hosting.secureserver.net"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 60
objCDOSYSCon.Fields.Update
With objCDOSYSMail
.To = strEmail
.BCc = "a#gmail.com"
.Cc = "b#gmail.com"
.From = "sales#b.com"
.Subject = "Thank you!"
.HTMLBody = "Hello<br></br><h3>Thank you for your enquiry. <br/>"
Set objCDOSYSMail = Nothing
Set objCDOSYSCon = Nothing
I don't know how to use their code.... please help
You can use the following code in a classic ASP page to send email with CDOSYS:
Set objMail = Server.CreateObject("CDO.Message")
Set objConf = Server.CreateObject("CDO.Configuration")
Set objFlds = objConf.Fields
objFlds.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 'cdoSendUsingPort
objFlds.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.your-site-url.com" 'your smtp server domain or IP address goes here
objFlds.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25 'default port for email
'uncomment next three lines if you need to use SMTP Authorization
'objFlds.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "your-username"
'objFlds.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "your-password"
'objFlds.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1 'cdoBasic
objFlds.Update
objMail.Configuration = objConf
objMail.FromName = "Your Name"
objMail.From = "your#address.com"
objMail.To = "destination#address.com"
objMail.Subject = "Email Subject Text"
objMail.TextBody = "The message of the email..."
objMail.Send
Set objFlds = Nothing
Set objConf = Nothing
Set objMail = Nothing
My ASP, classic ASP application is giving me a sever error on a Windows 2008 Server. It works fine on Windows 2003 server. The error is a 500 internal server error. Does CDO not work on Windows 2008?
EDIT
THe error is: The transport failed to connect to the server.
Here is my mail function:
function SendMail(mailFrom, mailTo, mailSubject, mailBody, bHtml)
Const cdoSendUsingMethod = _
"http://schemas.microsoft.com/cdo/configuration/sendusing"
Const cdoSendUsingPort = 2
Const cdoSMTPServer = _
"http://schemas.microsoft.com/cdo/configuration/smtpserver"
Const cdoSMTPServerPort = _
"http://schemas.microsoft.com/cdo/configuration/smtpserverport"
Const cdoSMTPConnectionTimeout = _
"http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"
Const cdoSMTPAuthenticate = _
"http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"
Const cdoBasic = 1
Const cdoSendUserName = _
"http://schemas.microsoft.com/cdo/configuration/sendusername"
Const cdoSendPassword = _
"http://schemas.microsoft.com/cdo/configuration/sendpassword"
Const smtpServer = "localhost"
Dim objConfig ' As CDO.Configuration
Dim objMessage ' As CDO.Message
Dim Fields ' As ADODB.Fields
' Get a handle on the config object and it's fields
Set objConfig = Server.CreateObject("CDO.Configuration")
Set Fields = objConfig.Fields
' Set config fields we care about
With Fields
.Item(cdoSendUsingMethod) = cdoSendUsingPort
.Item(cdoSMTPServer) = smtpServer
.Item(cdoSMTPServerPort) = 25
.Item(cdoSMTPConnectionTimeout) = 10
.Item(cdoSMTPAuthenticate) = cdoBasic
.Item(cdoSendUserName) = "username"
.Item(cdoSendPassword) = "password"
.Update
End With
Set objMessage = Server.CreateObject("CDO.Message")
Set objMessage.Configuration = objConfig
With objMessage
.To = mailTo
.From = mailFrom
.Subject = mailSubject
if bHtml then
.HtmlBody = mailBody
else
.TextBody = mailBody
end if
.Send
End With
Set Fields = Nothing
Set objMessage = Nothing
Set objConfig = Nothing
end function
It appears that the CDO/MAPI libraries aren't installed by default in Windows 2008:
You can download them from Microsoft.
Referenced from this blogpost:
If you want to write client
applications to run on computers that
use MAPI or CDO (for example, web
servers) and you don't want to install
(or can't install) either the Outlook
client or the Exchange management
tools, then you need to install the
MAPI/CDO libraries.