I used below code to get email content (.eml) from mailbox through Microsot Graph API.
var messages = graphServiceClient.Users[EmailAddress].MailFolders["inbox"].Messages.Request().Filter("isRead ne true").OrderBy("receivedDateTime").Top(1000).GetAsync().Result;
foreach (var message in messages)
{
using (var stream = graphServiceClient.Users[EmailAddress].Messages[message.Id].Content.Request().GetAsync().Result)
{
string emlFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EMAIL", Guid.NewGuid() + "" + ".eml");
using (FileStream fileStream = new FileStream(emlFilePath, FileMode.Create, FileAccess.Write))
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
fileStream.Write(bytes, 0, bytes.Length);
stream.Close();
}
}
}
It was working fine till today but some how today I am noticing email content is not fully downloading. If I try to download same email multiple time, every time I get different size of content (binary). surprisingly .eml file are able to open into Outlook but attachment gets corrupted.
Any suggestion most appreciate.
Related
I Have one 'System.Net.Mail.Attachment[] attachment' object , This object contains PDF,Xls,Doc or jpg file.
I want to save this attachment object to cloud server.
string sSavePath = "EmailAttachment/" + intSomeid + "/";
string strErrorMsg = string.Empty;
if ((attachments != null))
{
MemoryStream memoryStream = new MemoryStream();
StreamWriter memoryWriter = new StreamWriter(memoryStream);
memoryWriter.Write(attachments[0]);
memoryStream.Position = 0;
CloudFileSystem.SaveFileToCloudSystem(memoryStream, ref strErrorMsg, sSavePath, ConfigHelper.PrivateContainer, attachments[intI].Name);
memoryWriter.Dispose();
memoryStream.Dispose();
}
I have used the above code to save the file.
The File is saved to cloud but having 0 Byte data (Corrupted) File.
I have searched many places for that.
But not able to find error in the code.
Please suggest some solution in this case ?
Looks like you are making it yourself more difficult then needed. The Attachment instance has an ContentStream property which you don't need to feed through a MemoryStream at all.
string sSavePath = "EmailAttachment/" + intSomeid + "/";
string strErrorMsg = string.Empty;
if ((attachments != null))
{
CloudFileSystem.SaveFileToCloudSystem(
attachments[intI].ContentStream,
ref strErrorMsg,
sSavePath,
ConfigHelper.PrivateContainer,
attachments[intI].Name);
}
If you are doing this:
MemoryStream memoryStream = new MemoryStream();
StreamWriter memoryWriter = new StreamWriter(memoryStream);
memoryWriter.Write(attachments[0]);
You are probably writing the string representation of Attachment (ToString() gets called) and that is not the content of your file.
After so much r&d ,I have come up with the following answer
Memory stream of attachment object didn't work for me.
So I have approached temp path where the attachement was saved and do the following magical code :
string FileName = ((System.IO.FileStream (attachments[intI].ContentStream)).Name;
MemoryStream ms = new MemoryStream();
using (FileStream file = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
ms.Write(bytes, 0, (int)file.Length);
}
ms.Position = 0;
CloudFileSystem.SaveFileToCloudSystem(ms, ref strErrorMsg, sSavePath, ConfigHelper.PrivateContainer, attachments[intI].Name);
ms.Dispose();
I hope my question and answer helps you for your project
My company run an application that have to archive many kinds of files into some distants servers. The application works well but can't handle files larger than 1GB.
Here is the current function use to load the files to be uploaded to the distant server :
FileStream fs = File.OpenRead(fileToUploadPath);
byte[] fileArray = new byte[fs.Length];
fs.Read(fileArray, 0, fs.Length);
The byte array (when loaded successfully) was then splited into 100Mb bytes arrays and sent to the local server (using some WSDL web services) with the following function :
localServerWebService.SendData(subFileArray, filename);
I changed the function responsible for the file reading to use BufferendStream and I also wanted to improve the Webservice part so that it doesn't have to create a new stream at each call. I thought of somethings like this :
FileInfo source = new FileInfo(fileName);
using (FileStream reader = File.OpenRead(fileName))
{
using (FileStream distantWriter = localServerWebService.CreateWriteFileStream(fileName))
{
using (BufferedStream buffReader = new BufferedStream(reader))
{
using (BufferedStream buffWriter = new BufferedStream(distantWriter))
{
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
long bytesToRead = source.Length;
while (bytesToRead > 0)
{
int nbBytesRead = buffReader.Read(buffer, 0, buffer.Length);
buffWriter.Write(buffer, 0, nbBytesRead);
bytesRead += nbBytesRead;
bytesToRead -= nbBytesRead;
}
}
}
}
}
But this code can't compile and always give me the error Cannot convert MyNameSpace.FileStream into System.IO.FileStream at line using (FileStream distantWriter = localServerWebService.CreateWriteFileStream(fileName)). I can't cast MyNameSpace.FileStream into System.IO.FileStream either.
The web service method :
[WebMethod]
public FileStream CreateWriteFileStream(String fileName)
{
String RepVaultUP =
System.Configuration.ConfigurationSettings.AppSettings.Get("SAS_Upload");
String desFile = Path.Combine(RepVaultUP, fileName);
return File.Open(desFile, FileMode.Create, FileAccess.Write);
}
So can you guys please explain to me why is this not working?
P.S.: English is not my mothertong so I hope what i wrote is clearly undestandable.
So below is the code i'm using. Basically it just loops through an array, adds the files to the zip, then saves the zip to a memory stream and then emails the attachment.
When I look at the item in debug I can see that the zipfile has about 20 megabytes of data. When i receive the attachment it only has about 230 bits of data and there is no content. Any thoughts?
byteCount = byteCount + docs[holder].FileSize;
if (byteCount > byteLimit)
{
//create a new stream and save the stream to the zip file
System.IO.MemoryStream attachmentstream = new System.IO.MemoryStream();
zip.Save(attachmentstream);
//create the attachment and send that attachment to the mail
Attachment data = new Attachment(attachmentstream, "documentrequest.zip");
theMailMessage.Attachments.Add(data);
//send Mail
SmtpClient theClient = new SmtpClient("mymail");
theClient.UseDefaultCredentials = false;
System.Net.NetworkCredential theCredential = new System.Net.NetworkCredential("bytebte", "2323232");
theClient.Credentials = theCredential;
theClient.Send(theMailMessage);
zip = new ZipFile();
//iterate Document Holder
holder++;
}
else
{
//create the stream and add it to the zip file
//System.IO.MemoryStream stream = new System.IO.MemoryStream(docs[holder].FileData);
zip.AddEntry("DocId_"+docs[holder].DocumentId+"_"+docs[holder].FileName, docs[holder].FileData);
holder++;
}
The issue is here Attachment data = new Attachment(attachmentstream, "documentrequest.zip"); once I look at the attachment it has a size of -1 So whats the proper way to attach this item?
I suspect that the call to zip.Save closes the stream after it's written. You'll probably end up having to copy the bytes to an array and then create a new MemoryStream for reading. For example:
//create a new stream and save the stream to the zip file
byte[] streamBytes;
using (var ms = new MemoryStream())
{
zip.Save(ms);
// copy the bytes
streamBytes = ms.ToArray();
}
// create a stream for the attachment
using (var attachmentStream = new MemoryStream(streamBytes))
{
//create the attachment and send that attachment to the mail
Attachment data = new Attachment(attachmentstream, "documentrequest.zip");
theMailMessage.Attachments.Add(data);
// rest of your code here
}
I'm working on a little C# ASP.NET web app that pulls 3 files from my server, creates a zip of those files, and sends the zip file to an e-mail recipient.
The problem I'm having is finding a way to combine those 3 files without creating a zip file on the hard drive of the server. I think I need to use some sort of memorystream or filestream, but I'm in a little beyond my understanding when it comes to merging them into 1 zip file. I've tried SharpZipLib and DotNetZip, but I haven't been able to figure it out.
The reason I don't want the zip saved locally is that there might be a number of users on this app at once, and I don't want to clog up my server machine with those zips. I'm looking for 2 answers, how to zip files without saving the zip as a file, and how to attach that zip to a MailMessage.
Check this example for SharpZipLib:
https://github.com/icsharpcode/SharpZipLib/wiki/Zip-Samples#wiki-anchorMemory
using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
Try this:
public static Attachment CreateAttachment(string fileNameAndPath, bool zipIfTooLarge = true, int bytes = 1 << 20)
{
if (!zipIfTooLarge)
{
return new Attachment(fileNameAndPath);
}
var fileInfo = new FileInfo(fileNameAndPath);
// Less than 1Mb just attach as is.
if (fileInfo.Length < bytes)
{
var attachment = new Attachment(fileNameAndPath);
return attachment;
}
byte[] fileBytes = File.ReadAllBytes(fileNameAndPath);
using (var memoryStream = new MemoryStream())
{
string fileName = Path.GetFileName(fileNameAndPath);
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
{
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
using (var streamWriter = new StreamWriter(zipArchiveEntry.Open()))
{
streamWriter.Write(Encoding.Default.GetString(fileBytes));
}
}
var attachmentStream = new MemoryStream(memoryStream.ToArray());
string zipname = $"{Path.GetFileNameWithoutExtension(fileName)}.zip";
var attachment = new Attachment(attachmentStream, zipname, MediaTypeNames.Application.Zip);
return attachment;
}
}
I'm new to WCF, I want to Upload Multiple Images at a time using WCF from client,
The scenario is : I have 20 questions and each question may have 0 to 2 images , So I have to request to the service to save all data, What are the possible ways to get it right?,
I'm trying to get from last two days, But I'm able insert one Image at a time....
You have to add the stream conversion for each image and add the details to a list.
in the client side.
Stream stream = (Stream)openDialog.File.OpenRead();
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
BitmapImage bmi = new BitmapImage();
using (MemoryStream ms = new MemoryStream(bytes))
{
bmi.SetSource(ms);
newRow.Thumbnail = bmi;
}
in your service side
string filePath = ConfigurationManager.AppSettings.Get("ImageUploadPath");
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
filePath = filePath + "\\" + picture.FileName + "." + picture.FileType;
if (picture.FileName != string.Empty)
{
fileStream = File.Open(filePath, FileMode.Create);
writer = new BinaryWriter(fileStream);
writer.Write(picture.FileStream);
}