What repository can I save to without having admin rights? - c#

I'm facing a problem with an Internet application I'm working on right now (programming in C#).
I have to create a report and then send it via email to a certain user. After I create the report, I save it first into a temporary file, then attached it to the email giving the file path.
It's working on my computer because I have the administrator right, but it doesn't for my coworkers who don't have the admin right on their computer.
The file path I'm using is:
string filePath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.InternetCache),
fileName
);
Is there any temporary repository I can use that doesn't require admin rights?
Thanks.

Considering your ASP.NET tag, you should look at using Isolated Storage.

If you're using the built in mail classes in .Net, there's really no reason you need to write the attachment to a file at all, unless whatever is generating the report requires it.
This would work, assuming your report generator doesn't require file output and can just return bytes.
SmtpClient smtpClient = new SmtpClient(); //do whatever else you need to do here to configure this
byte[] report = GetReport();//whatever your report generator is
MailMessage m = new MailMessage();
//add your other mail fields (body, to, cc, subject etc)
using (MemoryStream stream = new MemoryStream(report))
{
m.Attachments.Add(new Attachment(stream,"reportfile.xls"));//just guessing, use the right filename for your attachment type
smtpClient.Send(m); //note that we send INSIDE this using block, because it will not actually read the stream until you send
//and you want to make sure not to dispose the stream before it reads it
}

How are you attaching it to the email? From the sounds of your question it appears that all you're doing is giving them the path to the file you create, rather than attaching it (as, once you attach it, it's embedded in the email and thus there are no paths involved).
If the web application is creating the temporary file then you can use the app_data folder (which is usually writable), and get a unique file name by using Path.GetRandomFileName().
So, something like
var myTemporaryFileName = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data",
Path.GetRandomFileName());
Then write your file to this temporary file name, then attach it to the email
MailMessage message = new MailMessage("recipient#example.com", "", ""
"subject",
"mail body");
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
ContentDisposition disposition = data.ContentDisposition;
disposition.FileName = "thefilenameyouwanttouseintheemail.ext";
message.Attachments.Add(data);
Now you can send it.
Don't forget to clean them up after though!

Related

Unable to identify the cause of error "The file is being used by another process"

Here is the c# code:
Program.cs
string path = #"E:\Example.txt";
if (!File.Exists(path))
{
File.Create(path);
}
// smtp code for sending emails
SmtpClient clientDetails = new SmtpClient();
...
MailMessage mailDetails = new MailMessage();
...
Attachment attachment = new Attachment(#"E:\Example.txt"); // Error "The process can not access the file because it is being used by another process" occurs here
mailDetails.Attachments.Add(attachment);
clientDetails.Send(mailDetails);
Problem: The error (The process can not access the file because it is being used by another process) occurs only when the "Example.txt" file is NOT already existing. Meaning, the error only occurs if File.Create(path);creates "Example.txt" file and then, smtp is supposed to send this file. So, I assume that File.Create() is using the file even after creation of file is completed. Please help me to prevent it from using the txt file once it is created.
Thanks in advance for all kinds of help.

Send Log file with email? Unity

I'm using Unity and C#
I want to send the output log file to my email at runtime, I used ByteSheep answer from this question and ArkaneX comment from this question to attach a txt file, now I was successful at sending txt files but how can I send the log file? I used this code to set the path to the log System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) + #"\Unity\Editor\Editor.log" and it does get the correct path, the problem is I'm getting
IOException: Sharing violation on path
when System.Net.Mail.Attachment attachment = new System.Net.Mail.Attachment(attachmentPath); is called.
I think I need o close the log file first but is that even possible?
maybe a solution would be duplicating the log file and sending the new one? would that work? if so how?
Any help is apprechiated.
Thanks in advance,
I had a similar situation and came up with below code. As the log file is in use by the program, I'm creating a copy of it and sending it as an email attachment.
private string logFilePathS = #Directory.GetCurrentDirectory() + #"\logs\log.txt";
private string logFilePathD = #Directory.GetCurrentDirectory() + #"\logs\log-" + String.Format("{0:dd-MMM-yyyy}", DateTime.Now) + ".txt";
File.Copy(logFilePathS, logFilePathD, true);
mailMessage.Attachments.Add(new Attachment(logFilePathD));
Once the email is sent, you can delete the new file created.
File.Delete(logFilePathD);

FileNotFoundException when trying to add an Attachment to Outlook Mailitem in C#

I am trying to send a mail on Outlook 2013 startup programmatically that has programmatically added attachments. Then the programm takes these attachments and creates a Password-locked Zip File and also adds this File as attachment. My Problem is, that I keep getting an
"System.IO.FileNotFoundException"
when executing
mail.Attachments.Add(pathToAttachment1);
I thought the path might not exist, but I can add this Path to a new zip-directory (using the same String), so it seems to be a Problem with the
Attachments.Add(Object)-Method.
MSDN says it is totally fine to give it a Pathname as String. In VBA it even worked, but in c# not (for whatever reason). Does somebody have an idea what i am doing wrong?
The Code i want to execute:
String pathToAttachment1 = #"C:\Testfile.txt";
//create a new ZipFile
ZipFile zipAttachment = new ZipFile("EncodedAttachments.zip");
zipAttachment.Password = "1234";
//Create a new MailItem
Outlook.MailItem mail = Application.CreateItem(Outlook.OlItemType.olMailItem);
//set Receiver, Body and Subject for the MailItem
mail.To = "foo";
mail.Body = "This is the body.";
mail.Subject = "This is the Subject.";
//This is working:
zipAttachment.AddFile(pathToAttachment1);
//This is the line where the Exception is thrown:
mail.Attachments.Add(pathToAttachment1);
This code is called in the Startup-Method handling the Outlook Startup Event. Does anyone have an idea what i might do wrong or could change to make it work?

How to check email for file using c#?

I receive an email with an excel file every week. I know there are probably better ways to accomplish my goal, but would it be possible to have a script task in SSIS that can open email, look for a specific file name as an attachment and then copy that file to another location?
Here is the scenario. This excel file is important for my team to have in a SQL database, and the provider of the excel source is only willing to email this excel file to us once per week. I then check my email, copy the file to a location where an SSIS dataflow task can then pick it up and insert it into a SQL table. I would like to automate this. So if my original approach is not doable, how else could this be automated? Aside from using a shared network location. Assume the excel file can ONLY come from the email. Using outlook/office 365, SSIS, SSMS, I have DBO access, and can use c#.
I'll admit that I'm ignorant on the email. If there is a procedure that the email client can actually execute to accomplish this, then I'd be all ears!
EDIT: I also have access to a network drive as I realize saving to my local machine may be impossible.
Simple Answer Yes it is Possible.
I had written a console program to process email on Office365 that I was also interfacing with SQL, so it definitely can be done. It isn't necessarily the easiest thing in the world but it is not too hard either.
You can use the Exchange Web Services (EWS) Managed API
Article on stating it is possible and the API documentation
https://msdn.microsoft.com/en-us/library/office/dd877012(v=exchg.150).aspx
Github location where you can find the API (note this link is directly form Microsoft's Site)
https://github.com/officedev/ews-managed-api
Link on how to reference the assembly which contains the second link above:
https://msdn.microsoft.com/en-us/library/office/dn528373(v=exchg.150).aspx
Create and Connect to Service
string emailAddress = 'YourEmail#Domain.com';
ExchangeService exService = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
exService.Credentials = new WebCredentials(emailAddress,"password");
you can autodiscover or if you know the URL just set it so 1 of these lines
exService.AutodiscoverUrl(_emailAddress, delegate { return true; });
exService.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
Find your Inbox & a Folder to Move the File To After Being Processed:
FolderView folderView = new FolderView(1);
folderView.PropertySet = new PropertySet(BasePropertySet.IdOnly);
folderView.PropertySet.Add(FolderSchema.DisplayName);
folderView.Traversal = FolderTraversal.Deep;
SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "ProcessedFolderName");
Folder Inbox = Folder.Bind(exService, WellKnownFolderName.Inbox);
FindFoldersResults folderResults = Inbox.FindFolders(searchFilter, folderView);
FolderId processedFolderId = folderResults.Folders[0].Id;
Find Messages That meet your criteria:
List<SearchFilter> searchFilterCollection = new List<SearchFilter();
searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.Subject,"Words in Subject"));
searchFilterCollection.Add(new SearchFilter.IsEqualTo(ItemSchema.HasAttachments,true));
searchFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.From,new EmailAddress("From#SendersDomain.com")));
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.And,searchFilterCollection);
ItemView view = new ItemView(50, 0, OffsetBasePoint.Beginning);
view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived, ItemSchema.Attachments);
view.Traversal = ItemTraversal.Shallow;
FindItemsResults<Item> findResults = exService.FindItems(WellKnownFolderName.Inbox,searchFilter,view);
Process the results and save the attachments when done move the message to another folder so you don't keep importing the same one.
foreach (Item i in findResults.Items)
{
foreach(FileAttachment attachment in i.Attachments)
{
attachment.Load(#"\\FilePathDirectory\" + attachment.FileName);
}
i.Move(processedFolderId);
}
you can expand the solution by testing if you get no results sending yourself an error message or throwing an error for SSIS to pickup and fail the job. It is likely that you will overwrite the file multiple times if you have multiple messages to process so you may consider adding something unique in the file name instead of just using the same one but that will present other challenges in SSIS as well.
anyway, its a start hope it helps.

C# get mail and its attachment from outlook

I've made program which one of the purposes is to open OutLook client where user can write his email, add attachments etc. After sending I want to get all attachments which were added to email, as well as all email in my program.
I tried to handle close event
((Microsoft.Office.Interop.Outlook.ItemEvents_10_Event)email.oMsg).Close += new Microsoft.Office.Interop.Outlook.ItemEvents_10_CloseEventHandler(GetAttachmentsInfo);
and then
if (email.oMsg.Attachments.Count > 0)
{
foreach (Microsoft.Office.Interop.Outlook.Attachment at in email.oMsg.Attachments )
{ attachments.Add(at); }
}
email is OutlookEMail
oMsg is Email Item
attachments is List<Attachment>
but when I close client Attachment throws exception that cannot find object. as well as these in List.
I know that Microsoft.Office.Interop.Outlook.Attachment is not a file, but only something like path to this file containing it name and size.
So question : is it possible to save attachments after client is closed in my program?
(Without using Email.SaveAttachments os SaveEmail methods, because it uses time and computer space)?
Here are two other options you could try:
1. You could listen for MailItem additions to the SentItems Folder via Folder.ItemAdd.
Outlook.Folder sentItems = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail) as Outlook.Folder;
sentItems.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(GetAttachmentsInfo);
2. You could attach to the MailItem.Send event.
((Outlook.ItemEvents_10_Event)MailItem).Send += new Outlook.ItemEvents_10_SendEventHandler(GetAttachmentsInfo);

Categories

Resources