how to save email body into text file in c# - c#

I'm trying to copy my inbox email to text file then search word in this text file. if this word exist i will use this word to query email-id from db finally forward this mail to this email-id.
my problem is i m not able to copy email into text file. msg variable always empty
this my code :
using (Pop3Client client = new Pop3Client())
{
client.Connect("pop.gmail.com", 995, true);
client.Authenticate("mymail#gmail.com", "pasword", AuthenticationMethod.UsernameAndPassword);
// Get the number of messages in the inbox
int messageCount = client.GetMessageCount();
for (int i = messageCount; i > 0; i--)
{
string msg = client.GetMessage(i).MessagePart.GetBodyAsText().ToString();
System.IO.File.WriteAllText(#"d:\\My File2.log", msg.ToString());
var body = System.IO.File.ReadLines(#"d:\\My File2.log");
if (body.Contains("cusotmer ID: X"))
{
getemailadress();
sendemail();
}
}
}

could you use this code :
var mailbody = ASCIIEncoding.ASCII.GetString(message.RawMessage);
like this :
using (Pop3Client client = new Pop3Client())
{
client.Connect("pop.gmail.com", 995, true);
client.Authenticate("mymail#gmail.com", "pasword", AuthenticationMethod.UsernameAndPassword);
// Get the number of messages in the inbox
int messageCount = client.GetMessageCount();
for (int i = messageCount; i > 0; i--)
{
string msg = ASCIIEncoding.ASCII.GetString(client.GetMessage(i).RawMessage);
System.IO.File.WriteAllText(#"d:\\My File2.log", msg);
var body = System.IO.File.ReadLines(#"d:\\My File2.log");
if (body.Contains("cusotmer ID: X"))
{
getemailadress();
sendemail();
}
}
}
And, advice: stop call .ToString() for already string objects.
And i cannot understand why you trying to save messageBody to a TextFile. Because WriteAllText function will overwrite this file on each loop.
So you wont find your all message end of this method. You can find only last message body in the textfile. Are you noticed this?

Related

Get HTML from Email Attachment using Pop3Client

I am using Pop3Client for reading email. The email I'm reading has some files attached. The attached files contain HTML content, so I want to read the file contents as HTML
My code
var Messages = new List<Message>(messageCount); // messageCount = total unread email
for (int i = 0; i < messageCount; i++)
{
Message getMessage = client.GetMessage(i + 1);
Messages.Add(getMessage);
}
int k = 1;
foreach (Message msg in Messages)
{
foreach (var attachment in msg.FindAllAttachments())
{
var html = attachment.GetBodyAsText();
}
}
Output
But I need the output in HTML format; how can I convert the output to HTML?

How do I check if user input is in data file C# and display correct message?

This is the data file named "ChargeAccounts.txt". I need to search this data file for a users account number entered in the textbox txtAccount.
5658845
4520125
7895122
8777541
8451277
1302850
8080152
4562555
5552012
5050552
7825877
1250255
1005231
6545231
3852085
7576651
7881200
4581002
I need to accomplish this using this array.
const int SIZE = 18;
string[] acct = new string[SIZE];
This is the code I have and it will only display "Account is invalid." even when I enter a account number from the data file.
private void FindAccountNumber()
{
System.IO.StreamReader file =
new System.IO.StreamReader("ChargeAccounts.txt");
acct = File.ReadAllLines("ChargeAccounts.txt");
for (int i = 0; i < acct.Length; i++)
{
if (txtAccount.Text.Contains(acct[i]))
{
lblMessage.Text = "Account is valid";
}
else
{
lblMessage.Text = "Account is invalid.";
}
}
file.Close();
}
You are iterating over all elements and updating lblMessage.Text for every iteration. So, you can get valid state only if txtAccount.Text contains last number in the file. You should break the for statement when valid number found, it will look like this
string message = "Account is invalid.";
for (int i = 0; i < acct.Length; i++)
{
if (txtAccount.Text.Contains(acct[i]))
{
message = "Account is valid";
break;
}
}
lblMessage.Text = message;

Having issues saving email attachment to directory

I am working on an application that crawls my email and sniffs out any emails with attachments. All attachment are being returned in the order they were received. Now I want to go a step further and would like to save any attachments in a local directory. I have been looking for documentation or examples but I have come up empty. I will show you a snippet of my code
This Function will get Email Attachments
public static List<IMessage> GetEmailAttachments()
{
OutlookServicesClient star_Mail_Box = Start_OutLook_Services();
try
{
var Email_Box = star_Mail_Box.Users["*****#dell.com"].Folders["Inbox"].Messages.Where(m => m.HasAttachments == true).Expand(m => m.Attachments).ExecuteAsync();
var messages = Email_Box.Result.CurrentPage;
foreach (var message in messages.OrderByDescending(m=> m.DateTimeReceived))
{
var attachments = message.Attachments.CurrentPage;
foreach (var attachment in attachments)
{
///This is where I will need to put my Logic.
}
}
}
catch (Exception ex)
{
Console.WriteLine("Not Able To Get This Mail Box" + ex.Message + "\n\nDetails : \n\n " + ex.InnerException);
Console.ReadLine();
}
return null; // returning null right now for testing
}
Ok so after looking at the attachment definition I figured I go through a byte array to achieve what I want. Here goes the Some code for my attachment loop.
foreach (FileAttachment attachment in attachments)
{
byte[] bytefiles = attachment.ContentBytes;
string path = #"C:\Top-Level\" + attachment.Name;
if (!string.IsNullOrEmpty(message.Subject))
{
path = #"C:\Top-Level\" + message.Subject + "." + attachment.ContentType;
}
File.WriteAllBytes(path, bytefiles);
}

I am getting raw text while reading emails using IMAP

I have taken some code from MSDN to read emails using IMAP Client. I have changed little bit code so i can only read unseen email.
I am writing all response in Richtextbox.
The problems is format of Body text of Email is unreadable while all other text is fine.
void ReadEmail()
{
try
{
// there should be no gap between the imap command and the \r\n
// ssl.read() -- while ssl.readbyte!= eof does not work because there is no eof from server
// cannot check for \r\n because in case of larger response from server ex:read email message
// there are lot of lines so \r \n appears at the end of each line
//ssl.timeout sets the underlying tcp connections timeout if the read or write
//time out exceeds then the undelying connection is closed
tcpc = new System.Net.Sockets.TcpClient("imap.gmail.com", 993);
ssl = new System.Net.Security.SslStream(tcpc.GetStream());
ssl.AuthenticateAsClient("imap.gmail.com");
receiveResponse("");
username = "charlie#gmail.com";
password = "********";
receiveResponse("$ LOGIN " + username + " " + password + " \r\n");
receiveResponse("$ LIST " + "\"\"" + " \"*\"" + "\r\n");
receiveResponse("$ SELECT INBOX\r\n");
receiveResponse("$ UID SEARCH UNSEEN\r\n");
MatchCollection collection= Regex.Matches(Result,#" (\d{1,4})");
foreach (Match m in collection)
{
UNREAD_UID.Add(int.Parse(m.Groups[1].Value));
}
foreach (int x in UNREAD_UID)
{
receiveResponse("$ FETCH " +x + " body[header]\r\n");
richTextBox1.Text += Environment.NewLine+"-----------------------------------------------------------------------------------------------------------------------"+Environment.NewLine;
receiveResponse("$ FETCH " +x + " body[text]\r\n");
richTextBox1.Text += Environment.NewLine + "###########################################################2" + Environment.NewLine;
richTextBox1.Update();
}
//receiveResponse("$ STATUS INBOX (MESSAGES)\r\n");
// int number = 1;
receiveResponse("$ LOGOUT\r\n");
}
catch (Exception ex)
{
Console.WriteLine("error: " + ex.Message);
}
finally
{
if (sw != null)
{
sw.Close();
sw.Dispose();
}
if (ssl != null)
{
ssl.Close();
ssl.Dispose();
}
if (tcpc != null)
{
tcpc.Close();
}
}
}
void receiveResponse(string command)
{
try
{
if (command != "")
{
if (tcpc.Connected)
{
dummy = Encoding.ASCII.GetBytes(command);
ssl.Write(dummy, 0, dummy.Length);
}
else
{
throw new ApplicationException("TCP CONNECTION DISCONNECTED");
}
}
ssl.Flush();
buffer = new byte[5120];
bytes = ssl.Read(buffer, 0, 5120);
sb.Append(Encoding.ASCII.GetString(buffer));
Result = sb.ToString();
richTextBox1.Text += Environment.NewLine + Environment.NewLine + Environment.NewLine + Environment.NewLine + sb.ToString();
sb = new StringBuilder();
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message);
}
}
Here is Sample of what i am getting
108 FETCH (BODY[TEXT] {25656}
DQoNCg0KDQo8IURPQ1RZUEUgaHRtbD4NCjxodG1sPg0KPGhlYWQ+DQo8dGl0bGU+TWlj
cm9zb2Z0IHR1cm5zIChhbG1vc3QpIGFueSBjYW1lcmEgaW50byBhIEtpbmVjdDwvdGl0
bGU+DQo8bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LVR5cGUiIGNvbnRlbnQ9InRleHQv
aHRtbDsgY2hhcnNldD1VVEYtOCI+DQo8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVu
dD0id2lkdGg9ZGV2aWNlLXdpZHRoIj4NCjwhLS0gRWZmaW5nIFdpbmRvd3MgOCBNYWls
IGNsaWVudC4gQWRkIC13ZWJraXQtbWluLWRldmljZS1waXhlbC1yYXRpbzogMSB0byBz
Y2FyZSBpdCBhd2F5IGZyb20gdGhpcyBiaXQuIC0tPg0KPHN0eWxlIHR5cGU9InRleHQv
Y3NzIj4NCkBtZWRpYSBzY3JlZW4gYW5kIChtYXgtZGV2aWNlLXdpZHRoOiA1MDBweCkg
YW5kICgtd2Via2l0LW1pbi1kZXZpY2UtcGl4ZWwtcmF0aW86IDEpIHsNCgkuYm9keS1j
b250YWluZXIgeyB3aWR0aDoxMDAlICFpbXBvcnRhbnQ7IH0NCgkuYmFubmVyICAgICAg
ICAgeyBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7IH0NCgkubW9iaWxlLWJhbm5lciAg
eyBkaXNwbGF5OiBibG9jayAhaW1wb3J0YW50OyB3aWR0aDozNDBweCAhaW1wb3J0YW50
OyBiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3d3dy5jb2RlcHJvamVjdC5jb20vc2NyaXB0
L21haWxvdXRzL3RlbXBsYXRlcy9uZXdzbGV0dGVyLWluc2lkZXIucG5nKSBuby1yZXBl
YXQgdG9wIGxlZ
Kindly help me.
You need to examine the Content-Transfer-Encoding header to undo Transfer encoding (in this case, that's Base64. Other alternatives are 7-bit or Quoted Printable). Or, better, download the entire message (Body[]) and apply a MIME parser/decoder to it to get an object representation of the headers, body, and attachments.
Max's answer above is correct, but I'm going to illustrate how to implement his suggestion using my MailKit library:
using (var client = new ImapClient ()) {
client.Connect ("imap.gmail.com", 993, true);
// since we're not using an OAuth2 token, remove it from the set
// of possible authentication mechanisms to try:
client.AuthenticationMechanisms.Remove ("XOAUTH2");
client.Authenticate ("charlie#gmail.com", "*****");
// SELECT the INBOX folder
client.Inbox.Open (FolderAccess.ReadWrite);
foreach (var uid in client.Inbox.Search (SearchQuery.NotSeen)) {
var message = client.Inbox.GetMessage (uid);
// at this point, 'message' is a MIME DOM that you can walk
// over to get the particular MIME-part that you want. For
// example, we could get a body part with a filename of
// "test.txt" using LINQ like this:
var attachment = message.BodyParts.OfType<MimePart> ()
.FirstOrDefault (x => x.FileName == "test.txt");
// decode the content to a MemoryStream:
using (var memory = new MemoryStream ()) {
attachment.ContentObject.DecodeTo (memory);
}
// since the attachment is probably a TextPart
// (based on the file extension above), we can actually
// use a simpler approach:
var textPart = attachment as TextPart;
if (textPart != null) {
// decode the content and convert into a 'string'
var text = textPart.Text;
}
}
client.Disconnect (true);
}

Deleting files fails as held by and existing process

I'm having issues with a bit of code that I am writing in C#.
I am sending a document using the MailMessage and SMTP components. I copy the files that I wish to send to a temp directory such as c:\temp, loop through the documents and attach them to the email.
The email sends fine, however when I try to delete the files from the temp directory, I get the following error:
The process can not access the file because it is being used by another process
I can't understand why this is happening. Below is the code that processes the documents
public void sendDocument(String email, string barcode, int requestid)
{
string tempDir = #"c:\temp";
//first we get the document information from the database.
Database db = new Database(dbServer, dbName, dbUser, dbPwd);
List<Document> documents = db.getDocumentByID(barcode);
int count = 0;
foreach (Document doc in documents)
{
string tempPath = tempDir + "\\" + doc.getBarcode() + ".pdf";
string sourcePath = doc.getMachineName() + "\\" + doc.getFilePath() + "\\" + doc.getFileName();
//we now copy the file from the source location to the new target location
try
{
//this copies the file to the folder
File.Copy(sourcePath, tempPath, false);
}
catch (IOException ioe)
{
count++;
//the file has failed to copy so we add a number to the file to make it unique and try
//to copy it again.
tempPath = tempDir + "\\" + doc.getBarcode() + "-" + count + ".pdf";
File.Copy(sourcePath, tempPath, false);
}
//we now need to update the filename in the to match the new location
doc.setFileName(doc.getBarcode() + ".pdf");
}
//we now email the document to the user.
this.sendEmail(documents, email, null);
updateSentDocuments(documents, email);
//now we update the request table/
db.updateRequestTable(requestid);
//now we clean up the documents from the temp folder.
foreach (Document doc in documents)
{
string path = #"c:\temp\" + doc.getFileName();
File.Delete(path);
}
}
I would of thought that the this.sendEmail() method would of sent the email before returning to the sendDocument method, as I think it is the smtp object that is causing the deletes to fail.
This is the sendEmail method:
public void sendEmail(List<Document> documents, String email, string division)
{
String SMTPServer = null;
String SMTPUser = null;
String SMTPPwd = null;
String sender = "";
String emailMessage = "";
//first we get all the app setting used to send the email to the users
Database db = new Database(dbServer, dbName, dbUser, dbPwd);
SMTPServer = db.getAppSetting("smtp_server");
SMTPUser = db.getAppSetting("smtp_user");
SMTPPwd = db.getAppSetting("smtp_password");
sender = db.getAppSetting("sender");
emailMessage = db.getAppSetting("bulkmail_message");
DateTime date = DateTime.Now;
MailMessage emailMsg = new MailMessage();
emailMsg.To.Add(email);
if (division == null)
{
emailMsg.Subject = "Document(s) Request - " + date.ToString("dd-MM-yyyy");
}
else
{
emailMsg.Subject = division + " Document Request - " + date.ToString("dd-MM-yyyy");
}
emailMsg.From = new MailAddress(sender);
emailMsg.Body = emailMessage;
bool hasAttachements = false;
foreach (Document doc in documents)
{
String filepath = #"c:\temp\" + doc.getFileName();
Attachment data = new Attachment(filepath);
emailMsg.Attachments.Add(data);
hasAttachements = true;
}
SmtpClient smtp = new SmtpClient(SMTPServer);
//we try and send the email and throw an exception if it all goes tits.
try
{
if (hasAttachements)
{
smtp.Send(emailMsg);
}
}
catch (Exception ex)
{
throw new Exception("EmailFailure");
}
}
How to I get around this problem with a process hogging the file I wish to delete.
I can delete the file(s) once the application finishes.
You're email message isn't being Disposed, try disposing it after you've sent it:
try
{
if (hasAttachements)
{
smtp.Send(emailMsg);
}
}
catch ...
finally
{
emailMsg.Dispose();
}
The first step is to figure out what process is holding onto the file in question. I would grab the SysInternals toolkit and use the handle.exe command to determine what process is holding onto the file.
Without knowing what process has the file open, there is no way to fix this problem.
Sysinternals Link: http://technet.microsoft.com/en-us/sysinternals/default.aspx
Here's a trick I just discoverred, which will hopefully be of use to other folk?
Before adding attachments to a message, create the attachment in a using wrapper. This ensures it gets disposed of correctly, allowing the file to be successfully deleted. I'm not sure if the send also needs to be in this loop; (when I tested, emails didn't get through at first, then half an hour later I got flooded, so decided to leave testing for a time when the network was a little calmer).
using (Attachment attachment = new Attachment(filename))
{
message.Attachments.Add(attachment);
client.SendAsync(message, string.Empty);
}
File.Delete(filename);
Works OK for me anyway :)
Good luck,
JB

Categories