I am new 2 C# and i have been given a task...
I have to write a C# code to download the email attachments from outlook 2007 to a local drive or any specified location.The program should be in such a way that, given any username and password it should connect to that particular users outlook and download the files specified from a particular from address or subject line.
Any kind of help is appreciated.
So you are using outlook in an Exchange 2007/2010 environment? If yes you cold take a look at EWS.
Go through the following piece of code. It should work!
Microsoft.Office.Interop.Outlook.Application app = null;
Microsoft.Office.Interop.Outlook._NameSpace ns = null;
Microsoft.Office.Interop.Outlook.PostItem item = null;
Microsoft.Office.Interop.Outlook.MAPIFolder inboxFolder = null;
//Microsoft.Office.Interop.Outlook.MAPIFolder subFolder = null;
try
{
app = new Microsoft.Office.Interop.Outlook.Application();
ns = app.GetNamespace("MAPI");
ns.Logon(null,null,false, false);
inboxFolder = ns.GetDefaultFolder (Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
//subFolder = inboxFolder.Folders["MySubFolderName"];
//folder.Folders[1]; also works
//Console.WriteLine("Folder Name: {0}, EntryId: {1}", subFolder.Name, subFolder.EntryID);
//Console.WriteLine("Num Items: {0}", subFolder.Items.Count.ToString());
for (int i = 1; i <= inboxFolder.Items.Count; i++)
{
item = (Microsoft.Office.Interop.Outlook.PostItem)inboxFolder.Items[i];
foreach (Microsoft.Office.Interop.Outlook.Attachments attachment in item.Attachments)
{
// Process the "attachment" object as per your requirement!
}
//Console.WriteLine("Item: {0}", i.ToString());
//Console.WriteLine("Subject: {0}", item.Subject);
//Console.WriteLine("Sent: {0} {1}", item.SentOn.ToLongDateString(), item.SentOn.ToLongTimeString());
//Console.WriteLine("Categories: {0}", item.Categories);
//Console.WriteLine("Body: {0}", item.Body);
//Console.WriteLine("HTMLBody: {0}", item.HTMLBody);
}
}
catch (System.Runtime.InteropServices.COMException ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
ns = null;
app = null;
inboxFolder = null;
}
Related
I have a windows service in C# .NET 4.6.1 that is building SSRS reports and sending the report to various network printers. All printers are installed locally on the server where the service is installed. All this was working on a Windows Server 2008R2 server and recently the client upgraded to Windows Server 2012R2 and now no printouts. I am getting no errors and when checking the job status on the printer I can see the job count on the printer increase by 1 and the PrintJobStatus.Spooling is true but nothing comes out on the printer.
private bool PrintSheet(AppPrintRequest model, PackagingEntities db)
{
try
{
var oPrinter = db.AppPrinters.Where(x => x.AppPrinterID == model.AppPrinterID).FirstOrDefault();
var lpsPrintServer = new LocalPrintServer();
var psPrintServer = new PrintServer();
var sbLog = new StringBuilder();
byte[] reportBytes = BuildSSRSReport(model);
PrintQueueCollection pqcAvailablePrinters;
if (!string.IsNullOrEmpty(oPrinter.AppPrinterServer))
{
pqcAvailablePrinters = lpsPrintServer.GetPrintQueues();
}
else
{
pqcAvailablePrinters = psPrintServer.GetPrintQueues();
}
sbLog.AppendFormat("System: {0} ", model.AppPrintRequestSystem);
sbLog.AppendFormat("Printer: {0} ", oPrinter.AppPrinterAddress);
foreach(var oAvailablePrinter in pqcAvailablePrinters)
{
sbLog.AppendFormat("Printer FullName: {0} ", oAvailablePrinter.FullName);
sbLog.AppendFormat("Printer Name: {0} ", oAvailablePrinter.Name);
sbLog.AppendFormat("Printer Description: {0} ", oAvailablePrinter.Description);
}
var oLaserPrinter = pqcAvailablePrinters.FirstOrDefault(pqCurrent => pqCurrent.Name.ToUpper() == oPrinter.AppPrinterAddress.ToUpper());
sbLog.AppendFormat("Report Bytes is null = {0} ", reportBytes == null);
sbLog.AppendFormat("Laser Print is null = {0} ", oLaserPrinter == null);
if (reportBytes != null && oLaserPrinter != null)
{
sbLog.AppendFormat("Report Bytes Length: {0} ", reportBytes.Length);
sbLog.AppendFormat("Laser Printer: {0} ", oLaserPrinter.Name);
sbLog.AppendFormat("Laser Printer Busy: {0} ", oLaserPrinter.IsBusy);
PrintSystemJobInfo oPrintJob = oLaserPrinter.AddJob();
sbLog.AppendFormat("Laser Printer Job Count: {0} ", oLaserPrinter.NumberOfJobs);
GetPrintJobStatus(oPrintJob, sbLog);
oPrintJob.JobStream.Write(reportBytes, 0, reportBytes.Length);
oPrintJob.JobStream.Close();
oPrintJob.Refresh();
sbLog.AppendFormat("Job Completed: {0} ", oPrintJob.IsCompleted);
NLogger.Debug(string.Format("Print Sheet: {0}", sbLog.ToString()));
return true;
}
NLogger.Debug(string.Format("Print Sheet: {0}", sbLog.ToString()));
return false;
}
catch (Exception ex)
{
NLogger.Fatal("PrintEngine_PrintSheet", ex);
return false;
}
}
I have been working on this small console app to read through a mailbox. It works fine but after it has finished reading through the mails, I want it to move them to the Deleted post folder. I found other questions related to this, but it didn't seem to fix it. I don't get any errors and the Seen flag works flawless. Feel free to comment in case of questions.
DateTimeOffset test = DateTime.Now;
using (var client = new ImapClient())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect("Imap.outlook.com", 993, true);
client.AuthenticationMechanisms.Remove("XOAUTH2");
client.Authenticate("Email#mail.com", "password");
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadWrite);
Console.WriteLine("Total messages: {0}", inbox.Count);
Console.WriteLine("Recent messages: {0}", inbox.Recent);
for (int i = 0; i < inbox.Count; i++)
{
var message = inbox.GetMessage(i);
Console.OutputEncoding = System.Text.Encoding.ASCII;
test = message.Date;
inbox.AddFlags(i , MessageFlags.Seen, true);
inbox.AddFlags(i, MessageFlags.Deleted, true); // Doesn't do anything.
Console.WriteLine("Emne: {0}", message.Subject);
Console.WriteLine("Fra: {0}", message.From);
Console.WriteLine("id: {0}", test);
Console.WriteLine(" ");
}
Console.ReadLine();
client.Disconnect(true);
}
Hello i have found the answer, after alot of searching and testing,
inbox.AddFlags(i, MessageFlags.Deleted, true);
marked it for being deleted, but didn't move it to either Delete post or anything, I found that if i run the
inbox.Expunge();
it removes all the messages marked for being deleted.
I am trying to send an email from inside my C# console App. I have added the references and using statements but it seems I have not added everything I need. This is the first time I have ever attempted to do this so I figure there is something I have forgotten.
I got this code snippet from the MSDN site http://msdn.microsoft.com/en-us/library/vstudio/ms269113(v=vs.100).aspx
Here is the code that I am getting issues with in VS 2010
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
namespace FileOrganizer
{
class Program
{
private void CreateMailItem()
{
//Outlook.MailItem mailItem = (Outlook.MailItem)
// this.Application.CreateItem(Outlook.OlItemType.olMailItem);
Outlook.Application app = new Outlook.Application();
Outlook.MailItem mailItem = app.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.Subject = "This is the subject";
mailItem.To = "someone#example.com";
mailItem.Body = "This is the message.";
mailItem.Attachments.Add(logPath);//logPath is a string holding path to the log.txt file
mailItem.Importance = Outlook.OlImportance.olImportanceHigh;
mailItem.Display(false);
}
}
}
replace the line
Outlook.MailItem mailItem = (Outlook.MailItem)
this.Application.CreateItem(Outlook.OlItemType.olMailItem);
with
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem mailItem = app.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
Hope this helps,
This is how you can send an email via Microsoft Office Outlook. In my case I was using Office 2010, but I suppose it should work with newer versions.
The upvoted sample above just displays the message. It does not send it out. Moreover it doesn't compile.
So first you need to add these references to your .NET project:
Like I said in my comment to his OP:
You will need to add the following references: (1) From .NET tab add
Microsoft.Office.Tools.Outlook for runtime v.4.0.*, then (2) again
from .NET tab add Microsoft.Office.Interop.Outlook for version
14.0.0.0 in my case, and (3) COM object Microsoft Office 12.0 Object Library for Microsoft.Office.Core.
Then here's the code to send out emails:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Configuration;
using System.IO;
using System.Net.Mail;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
public enum BodyType
{
PlainText,
RTF,
HTML
}
//....
public static bool sendEmailViaOutlook(string sFromAddress, string sToAddress, string sCc, string sSubject, string sBody, BodyType bodyType, List<string> arrAttachments = null, string sBcc = null)
{
//Send email via Office Outlook 2010
//'sFromAddress' = email address sending from (ex: "me#somewhere.com") -- this account must exist in Outlook. Only one email address is allowed!
//'sToAddress' = email address sending to. Can be multiple. In that case separate with semicolons or commas. (ex: "recipient#gmail.com", or "recipient1#gmail.com; recipient2#gmail.com")
//'sCc' = email address sending to as Carbon Copy option. Can be multiple. In that case separate with semicolons or commas. (ex: "recipient#gmail.com", or "recipient1#gmail.com; recipient2#gmail.com")
//'sSubject' = email subject as plain text
//'sBody' = email body. Type of data depends on 'bodyType'
//'bodyType' = type of text in 'sBody': plain text, HTML or RTF
//'arrAttachments' = if not null, must be a list of absolute file paths to attach to the email
//'sBcc' = single email address to use as a Blind Carbon Copy, or null not to use
//RETURN:
// = true if success
bool bRes = false;
try
{
//Get Outlook COM objects
Outlook.Application app = new Outlook.Application();
Outlook.MailItem newMail = (Outlook.MailItem)app.CreateItem(Outlook.OlItemType.olMailItem);
//Parse 'sToAddress'
if (!string.IsNullOrWhiteSpace(sToAddress))
{
string[] arrAddTos = sToAddress.Split(new char[] { ';', ',' });
foreach (string strAddr in arrAddTos)
{
if (!string.IsNullOrWhiteSpace(strAddr) &&
strAddr.IndexOf('#') != -1)
{
newMail.Recipients.Add(strAddr.Trim());
}
else
throw new Exception("Bad to-address: " + sToAddress);
}
}
else
throw new Exception("Must specify to-address");
//Parse 'sCc'
if (!string.IsNullOrWhiteSpace(sCc))
{
string[] arrAddTos = sCc.Split(new char[] { ';', ',' });
foreach (string strAddr in arrAddTos)
{
if (!string.IsNullOrWhiteSpace(strAddr) &&
strAddr.IndexOf('#') != -1)
{
newMail.Recipients.Add(strAddr.Trim());
}
else
throw new Exception("Bad CC-address: " + sCc);
}
}
//Is BCC empty?
if (!string.IsNullOrWhiteSpace(sBcc))
{
newMail.BCC = sBcc.Trim();
}
//Resolve all recepients
if (!newMail.Recipients.ResolveAll())
{
throw new Exception("Failed to resolve all recipients: " + sToAddress + ";" + sCc);
}
//Set type of message
switch (bodyType)
{
case BodyType.HTML:
newMail.HTMLBody = sBody;
break;
case BodyType.RTF:
newMail.RTFBody = sBody;
break;
case BodyType.PlainText:
newMail.Body = sBody;
break;
default:
throw new Exception("Bad email body type: " + bodyType);
}
if (arrAttachments != null)
{
//Add attachments
foreach (string strPath in arrAttachments)
{
if (File.Exists(strPath))
{
newMail.Attachments.Add(strPath);
}
else
throw new Exception("Attachment file is not found: \"" + strPath + "\"");
}
}
//Add subject
if(!string.IsNullOrWhiteSpace(sSubject))
newMail.Subject = sSubject;
Outlook.Accounts accounts = app.Session.Accounts;
Outlook.Account acc = null;
//Look for our account in the Outlook
foreach (Outlook.Account account in accounts)
{
if (account.SmtpAddress.Equals(sFromAddress, StringComparison.CurrentCultureIgnoreCase))
{
//Use it
acc = account;
break;
}
}
//Did we get the account
if (acc != null)
{
//Use this account to send the e-mail.
newMail.SendUsingAccount = acc;
//And send it
((Outlook._MailItem)newMail).Send();
//Done
bRes = true;
}
else
{
throw new Exception("Account does not exist in Outlook: " + sFromAddress);
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: Failed to send mail: " + ex.Message);
}
return bRes;
}
And here's how you'd use it:
List<string> arrAttachFiles = new List<string>() { #"C:\Users\User\Desktop\Picture.png" };
bool bRes = sendEmailViaOutlook("senders_email#somewhere.com",
"john.doe#hotmail.com, jane_smith#gmail.com", null,
"Test email from script - " + DateTime.Now.ToString(),
"My message body - " + DateTime.Now.ToString(),
BodyType.PlainText,
arrAttachFiles,
null);
You need to cast the
app.CreateItem(Outlook.OlItemType.olMailItem)
object in
Outlook.MailItem mailItem = app.CreateItem(Outlook.OlItemType.olMailItem)
to
Outlook.MailItem type
since no implicit casting is available.
Replace
Outlook.MailItem mailItem = app.CreateItem(Outlook.OlItemType.olMailItem);
with
Outlook.MailItem mailItem = (Outlook.MailItem)app.CreateItem(Outlook.OlItemType.olMailItem);
I'm developing a desktop application that has mail sending option. I have the following code to that and it works perfect for only 1 recipient:
DialogResult status;
status = MessageBox.Show("Some message", "Info", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (status == DialogResult.OK)
{
try
{
// Create the Outlook application.
Outlook.Application oApp = new Outlook.Application();
// Create a new mail item.
Outlook.MailItem oMsg = (Outlook.MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
// Set HTMLBody.
//add the body of the email
oMsg.HTMLBody = "<html>" +
"<body>" +
"some html text" +
"</body>" +
"</html>";
int iPosition = (int)oMsg.Body.Length + 1;
//Subject line
oMsg.Subject = txt_mailKonu.Text;
oMsg.Importance = Outlook.OlImportance.olImportanceHigh;
// Recipient
Outlook.Recipients oRecips = (Outlook.Recipients)oMsg.Recipients;
//Following line causes the problem
Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add(senderForm.getRecipientList().ToString());
oRecip.Resolve();
//oRecip.Resolve();
// Send.
oMsg.Send();
// Clean up.
oRecip = null;
oRecips = null;
oMsg = null;
oApp = null;
MessageBox.Show("Successful", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception)
{
MessageBox.Show("Failed", "Eror", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I get the error at the bold line where I'm adding multiple recipients in the following pattern:
john.harper#abcd.com; adam.smith#abcd.com
It works fine for 1 address but when I get multiple addresses separated it throws COM Exception - Outlook cannot resolve one or more names.
Hope you'll help me with this.
Did you try to add multiple recipients to oMsg.Recipients?
// I assume that senderForm.getRecipientList() returns List<String>
foreach(String recipient in senderForm.getRecipientList())
{
Outlook.Recipient oRecip = (Outlook.Recipient)oRecips.Add(recipient);
oRecip.Resolve();
}
If needed, you could explode senderForm.getRecipientList().ToString() with
String [] rcpts = senderForm.getRecipientList().ToString().Split(new string[] { "; " }, StringSplitOptions.None);
and use new object in foreach loop.
since a few days I'm trying to rename the sent mail folder, deleted elements and the inbox folder via c#.
I've tryed something like this:
List<Outlook.MailItem> mailItems = new List<Outlook.MailItem>();
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace outlookNs = app.GetNamespace("MAPI");
// Add PST file (Outlook Data File) to Default Profile
outlookNs.AddStore(pstFilePath);
Outlook.MAPIFolder rootFolder = outlookNs.Stores[pstName].GetRootFolder();
Outlook.Folders subFolders = rootFolder.Folders;
foreach (Outlook.Folder folder in subFolders)
{
folder.Name = (folder.Name == "deleted Elements"?"deleted":folder.Name);
}
But without success. I always get the exceptiion that I do not have permissions to change the name. Other custom created folders I'm able to rename without any problems.
Is there something to do to unlock the folder?
Or is there an other possibility to access the folders?
Thanks a lot
Edit: The Expetion is: You do not have permissions.
public string RenameFolder(string name, string folderid)
{
Outlook.Application app = new Outlook.Application();
Outlook.NameSpace ns = null;
Outlook.Folder folder = null;
string n= null;
try
{
ns = app.GetNamespace("MAPI");
folder = ns.GetFolderFromID(folderid) as Outlook.Folder;
n=folder.Name;
folder.Name = (folder.Name = name) ;
return n + " has been successfully changed to " + folder.Name;
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
if (app != null)
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(app);
}
if (folder != null)
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder);
}
if (ns != null)
{
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ns);
}
}
}
this code is working for me..when i run visual studio in administator mode..