Attachment Excel File from Stream in ASP.NET? - asp.net

I have an excel document.I want to mail it as attachment from stream.
It sended mail with attachment but i cant open excel file correctly
this is my code:
public static string EPostaGonder(...,Stream AttachmentStream,string AttachmentFileName)
{
.
.
.
SmtpClient mailClient = new SmtpClient(Host, Port);
mailClient.EnableSsl = true;
NetworkCredential cred = new NetworkCredential(KullaniciAdi, Sifre);
mailClient.Credentials = cred;
MailMessage ePosta = new MailMessage();
ePosta.IsBodyHtml = true;
ePosta.From = new MailAddress(Kimden, Isim);
foreach (string Kime_ in Kime.Split(';'))
{
if (Kime_.Trim() != "")
ePosta.To.Add(Kime_.Trim());
ePosta.Subject = Konu;
ePosta.Body = Mesaj.Replace("\n","<br/>");
if (Cc != "")
ePosta.CC.Add(Cc);
if (AttachmentStream != null)
{
AttachmentStream .Seek(0, SeekOrigin.Begin);
ePosta.Attachments.Add(
new Attachment(AttachmentStream, AttachmentFileName + ".xlsx"));
}
try
{
//mailClient.SendAsync(ePosta, (object)ePosta);
mailClient.Send(ePosta);
return "Done";
}
catch (SmtpException SmtpException_)
{
return SmtpException_.Message;
}
}

Use following code to add Attachment in mail. Simply pass the file path to Attachment constructor.
Attachment attachment = new Attachment(file);
ePosta.Attachments.Add(attachment);
Add an attachment from stream:
ePosta.Attachments.Add( new Attachment( AttachmentStream, filename, "application/msexcel" ));

Try something like
var attach = new MailAttachment(Server.MapPath(strFileName));
ePosta.Attachments.Add(attach);
Have a look at this article about ASP.NET email with multiple attachments

Related

Sftp upload from memory stream asp.net

I am trying to upload a csv file that is created from a query and upload via sftp.
I am trying to avoid creating a file and then reading the file to upload it by keeping the data in memory.
Thanks in advance
var customerAddresses = addresses.Select(p => new { p.Customer.Name, p.Customer.AlternateName, p.City, p.StateProvince });
using (var memoryStream = new MemoryStream())
{
//if you pass a file path to streamWriter it creates a csv with the correct format and data
using (var streamWriter = new StreamWriter())
{
using (var csv = new CsvWriter(streamWriter))
{
csv.WriteRecords(customerAddresses);
var fileName = DateTime.UtcNow.ToString(dateFromat) + destinationFileName;
var privateKey = new PrivateKeyFile(sshKeyLocation);
var connectionInfo = new PrivateKeyConnectionInfo(address,
username,
new PrivateKeyFile(sshKeyLocation)
);
memoryStream.Flush();
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
client.ChangeDirectory(serverDirectory);
client.UploadFile(memoryStream, fileName); //is always an empty file
}
}
}
Try adding setting memoryStream Position to beginning with Seek before calling UploadFile and calling streamWriter.Flush();, not memoryStream.Flush():
streamWriter.Flush();
memoryStream.Seek(0, SeekOrigin.Begin);
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
client.ChangeDirectory(serverDirectory);
client.UploadFile(memoryStream, fileName);
}
I never figured out how to get it to work with MemoryStream and changed to to write a file and then read and upload that file.
public HttpResponseMessage Post([FromBody] CustomerIds[] CustomerIds)
{
try
{
if(CustomerIds.Length == 0)
{
throw new Exception("No customer ids passed in post body.");
}
else if (!File.Exists(sshKeyLocation))
{
throw new Exception("Missing ssh file.");
}
if(!Directory.Exists(localDirectory))
{
Directory.CreateDirectory(localDirectory);
}
var customerAddresses = _repository.GetPrimaryAddress(CustomerIds.Select(c => c.Id))
.Select(p => new
{
p.Customer.Name,
p.Customer.AlternateName,
p.City,
p.StateProvince
}
);
if (customerAddresses == null || !customerAddresses.Any())
{
throw new Exception("No customer addresses found for selected customers.");
}
var fileName = DateTime.UtcNow.ToString(dateFromat) + destinationFileName;
var localFilePath = Path.Combine(localDirectory, fileName);
CreateFile(customerAddresses, localFilePath);
UploadFile(localFilePath, fileName);
return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}
catch(Exception error)
{
logger.Error(error, error.Message);
throw error;
}
}
private void CreateFile(IEnumerable<object> customerAddresses, string filePath)
{
using (TextWriter streamWriter = new StreamWriter(filePath))
using (var csv = new CsvWriter(streamWriter))
{
csv.WriteRecords(customerAddresses);
}
}
private void UploadFile(string localFilePath, string destinationFileName)
{
var connectionInfo = new PrivateKeyConnectionInfo(address,
username,
new PrivateKeyFile(sshKeyLocation)
);
using (var fileStream = new FileStream(localFilePath, FileMode.Open))
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
client.ChangeDirectory(serverDirectory);
client.UploadFile(fileStream, destinationFileName);
}
}
I've run out of time to continue trying to upload using the MemoryStream and will just have to use this solution. Disappointed I couldn't get it to work.

ClosedXML can't delete file after saving Workbook "process in use"

So here's the code:
string filename = #"c:\test.xlsx";
using (XLWorkbook wb = CreateWorkbookInformation())
{
wb.SaveAs(filename);
Email.EmailAsAttachment(filename);
}
File.Delete(filename);
It creates the Workbook information just fine, it saves the file fine, it emails the file fine as an attachment... However, when I try to delete file (after the using statement), it states the "process is in use". There shouldn't be anything keeping the file open?!? What process am I missing that I should close in order to delete the file?
Ahh, nevermind, had nothing to do with ClosedXML, had everything to do with attaching the file to the email and not using a proper usingstatement for the attachment. So the attachment process was keeping the file open.
Thank you so much for posting this answer!!!
I went crazy trying to understand what's my problem!
I did as you suggested and used the proper using statement:
using (MailMessage mail = new MailMessage(senderAdress, emailAdress))
{
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = ConfigurationManager.AppSettings["SMTPHostName"];
if (string.IsNullOrWhiteSpace(client.Host))
{
errorMsg = "ConfigurationManager.AppSettings[\"SMTPHostName\"] not found";
return false;
}
mail.Subject = subject;
mail.IsBodyHtml = isBodyHtml;
mail.Body = body;
if (!string.IsNullOrWhiteSpace(attachmentFullPath))
{
if (File.Exists(attachmentFullPath))
{
System.Net.Mime.ContentType contentType = new System.Net.Mime.ContentType();
contentType.MediaType = System.Net.Mime.MediaTypeNames.Application.Octet;
contentType.Name = Path.GetFileName(attachmentFullPath);
mail.Attachments.Add(new Attachment(attachmentFullPath, contentType));
}
else
{
errorMsg = "Attachment File Doesn't Exist: " + attachmentFullPath;
return false;
}
}
client.Send(mail);
}

Odata naming file return error message of the

I have this custom Odata function to download pdf from download pdf database. I have some issues
1.with Pdf name does not name "reportname.pdf" it is named response.pdf as
2.return error message of reportBinary is null
[HttpGet]
[ODataRoute("GetDownloadReport(downloadId={downloadId})")]
public HttpResponseMessage GetDownloadReport(Guid downloadId)
var received = DateTime.UtcNow;
byte[] reportBinary = null;
string queryString = "SELECT report FROM downloads WHERE id = #downloadId ";
bool success = false;
using (SqlConnection conn = new SqlConnection(connectionString))
{
//get the binary from database
}
HttpResponseMessage response = null;
try
{
if (reportBinary == null)
return Request.CreateResponse(HttpStatusCode.Gone);
response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new ByteArrayContent(reportBinary);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "PORTName.pdf"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
}
try to set filename manually:
String headerInfo = "attachment; filename=" + System.Web.HttpUtility.UrlPathEncode("PORTName.pdf");
response.Content.Headers.Add("Content-Disposition", headerInfo);
I'm not sure what do you want to do about error message, but if you mean setting string content, just set it ;)
response = Request.CreateResponse(HttpStatusCode.Gone);
response.Content = new StringContent(...);
return response;
Consider using NotFound instead of Gone status code (Gone has very specific meaning).

Activation code is not displaying in url after click on the link

I am sending a link using email to create password but while sending link in an email i have attach my Activation Code also to display with link but it is not displaying when i click on link though in debugging i'm getting the link with Activation Code. Below is my code to add link in Body section
body+=#"<br /><a href='http://localhost:49234/Index.aspx?ActivationCode='"+objUserDetailsBE.ActivationCode+"'>Create a login to account</a>";
I am getting only till http://localhost:49234/Index.aspx?ActivationCode= in browser after click on the link Please let me know where i am doing wrong.
Adding code as per in comments:
string emailAddress = txtEmailAddress.Text;
string subject = "Login Credentials For Nth Star";
string body = string.Format("Hello,");
body+=#"<br /><a href='http://localhost:49234/Index.aspx?ActivationCode='"+objUserDetailsBE.ActivationCode+"'>Create a login to account</a>";
Email.SendMail(objemail, emailAddress, subject, body, "");
and below is my 'SendMail' method
public static bool SendMail(EmailConfigurationBE objEmailConfig, string toEmailAddresses, string subject, string body, string mailAttachments)
{
char[] splitter = { ';' };
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(objEmailConfig.Email);
mailMessage.Subject = subject;
mailMessage.Body = body;
mailMessage.IsBodyHtml = true;
mailMessage.Priority = MailPriority.High;
string[] multi = toEmailAddresses.Split(';');
string[] multipath = mailAttachments.Split(';');
foreach (string MultiemailId in multi)
{
mailMessage.To.Add(new MailAddress(MultiemailId));
}
if (mailMessage.To.Count > 0)
{
//Adding Multiple Attachments
if (mailAttachments != "")
{
foreach (string Multipath1 in multipath)
{
Attachment attachFile = new Attachment(Multipath1);
mailMessage.Attachments.Add(attachFile);
}
}
SmtpClient smtpClient = new SmtpClient();
try
{
smtpClient.Host = objEmailConfig.SMTPServer;
smtpClient.EnableSsl = EnableSsl;
System.Net.NetworkCredential NetworkCred = new System.Net.NetworkCredential();
NetworkCred.UserName = objEmailConfig.Email;
NetworkCred.Password =objEmailConfig.Password;
smtpClient.UseDefaultCredentials = true;
smtpClient.Credentials = NetworkCred;
smtpClient.Port =Convert.ToInt32(objEmailConfig.PortNumber);
smtpClient.Send(mailMessage);
return true;
}
catch
{
mailMessage = null;
smtpClient = null;
return false;
}
}
else
{
return false;
}
}
It looks like a simple quoting problem. Look
<a href='http://localhost:49234/Index.aspx?ActivationCode='"+objUserDetailsBE.ActivationCode+"'
In here you have a single quote before http, another one after ActivationCode= and third one at the end. Looks like one is redundant, and that breaks your markup.
Correct version:
body+=#"<br /><a href='http://localhost:49234/Index.aspx?ActivationCode="+objUserDetailsBE.ActivationCode+"'>Create a login to account</a>";
The only change I did was to remove the single quote after ActivationCode=.
Also make sure the active code does not contain symbols like quotes or <>, that can also break the markup.

Sending Emails with BCC list not working

I am trying to send emails to a single 'To' recipient, and a list of 'Bcc' recipients.
The list of Bcc recipients is a list of string, and they are successfully being added to the mailMessage's Bcc collection, but not actually being sent. If I add the same list to the message's 'Cc' collection it works fine. Just not the Bcc collection.
The code I'm using is this:
public void SendEmailMessage(String FromAddress, String ToAddress, String Subject, String Body, List<String> CCAddress, List<String> BccAddress, String Filepath)
{
using (SmtpClient mailClient = new SmtpClient())
{
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(FromAddress);
mailMessage.To.Add(new MailAddress(ToAddress));
foreach (String _email in CCAddress)
{
mailMessage.CC.Add(new MailAddress(_email));
}
foreach (String _email in BccAddress)
{
mailMessage.Bcc.Add(new MailAddress(_email));
}
mailMessage.Priority = MailPriority.Normal;
mailMessage.Subject = Subject;
if (Filepath != string.Empty)
{
Attachment _attachment = new Attachment(Filepath, MediaTypeNames.Application.Octet);
mailMessage.Attachments.Add(_attachment);
}
AlternateView plainTextView = AlternateView.CreateAlternateViewFromString(GetTextonly(Body), null, "text/plain");
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(Body, null, "text/html");
mailMessage.AlternateViews.Add(plainTextView);
mailMessage.AlternateViews.Add(htmlView);
SmtpClient smtpClient = new System.Net.Mail.SmtpClient();
smtpClient.Send(mailMessage);
}
}
any ideas?
one thing i didn't mention is that the mail is put in a pickup directory rather than sent direct.
I found a blog which explains that bcc addresses aren't sent if using a pickup directory, and you can put them in the retry directory instead. This solved my problem with an easy fix:
Unable to send Bcc using System.Net.Mail when specifying a Pickup Directory(Exchange 2007/Exchange 2010) in code
As a workaround, you could send your email explicitly to the BCC address.
After you've successfully sent your email:
mailClient.Send(mailMessage);
Clear the To address collection, then add your BCC address as a To address, and resend.
mailMessage.To.Clear(); // clear the existing To & Cc fields
mailMessage.Cc.Clear();
mailMessage.To.Add(new MailAddress("bcc#address.com","CopyAddress"));
mailClient.Send(mailMessage);
I created a test application and ran SmptForDev to capture any emails going out from my local IIS. I used the code below and it works fine. All I've really done to your code is tidy it up and it works fine. I also decompiled System.Net.Mail.SmtpClient to see what it does under the hood, the To address and Bcc addresses are all put into one collection, if one address is sending it's good to assume they all are.
public void SendEmailMessage(string fromAddress, string toAddress, string subject, string body, IEnumerable<string> ccAddress, IEnumerable<string> bccAddress, string filepath)
{
using (var mailClient = new SmtpClient())
{
var mailMessage = new MailMessage(fromAddress, toAddress);
foreach (var email in ccAddress)
{
mailMessage.CC.Add(new MailAddress(email));
}
foreach (var email in bccAddress)
{
mailMessage.Bcc.Add(new MailAddress(email,"Matty Boy"));
}
mailMessage.Priority = MailPriority.Normal;
mailMessage.Subject = subject;
if (!string.IsNullOrEmpty(filepath))
{
var attachment = new Attachment(filepath, MediaTypeNames.Application.Octet);
mailMessage.Attachments.Add(attachment);
}
var plainTextView = AlternateView.CreateAlternateViewFromString(GetTextonly(body), null, "text/plain");
var htmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
mailMessage.AlternateViews.Add(plainTextView);
mailMessage.AlternateViews.Add(htmlView);
mailClient.Send(mailMessage);
}
}

Resources