DonationCoder.com Forum

Other Software => Developer's Corner => Topic started by: kyrathaba on September 30, 2010, 10:03 PM

Title: Check Gmail using C#
Post by: kyrathaba on September 30, 2010, 10:03 PM
I've scoured the web for several days, looking for code allowing me to check my Gmail account programmatically in an application written in C#.  Found lots of examples (most pointing back to the OpenPop library), but no working examples -- and haven't been able to hack together my own working example either.

I have the same luck when I try to find actual working C# code to upload a file to a website directory using C#.  So any help in that regard would also be much appreciated.
Title: Re: Check Gmail using C#
Post by: wraith808 on September 30, 2010, 10:42 PM
I uploaded a simple FTP class to snipplr that might help.  You can find it at http://snipplr.com/view/16451/simpleftp-class/.  Let me know if you have any questions.
Title: Re: Check Gmail using C#
Post by: Carol Haynes on October 01, 2010, 02:31 AM
If you use labels and filters in your GMail account you will need to use IMAP to access all of your mail. POP will only grab things that are labelled 'inbox'.
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 01, 2010, 07:28 AM
Thank you both for your help.

Wraith, can the snippet be downloaded without the line numbers?  And do you have a short snippet showing the class in use?  For example, say I want to download ...

ftp://mysite.com/myfile.jpg

to C:/localFile.jpg

username="myName"

password="myPass"

Could you snow me a snippet that will do that?  I know I must seem dense (probably AM), but it just helps.


Carol, thanks for the tip about POP; didn't know that.
Title: Re: Check Gmail using C#
Post by: Eóin on October 01, 2010, 07:28 AM
Following on from Carol's suggestion to use IMAP, you should find the info and links in this StackOverflow question very helpful- Accessing Imap in C#? (http://stackoverflow.com/questions/670183/accessing-imap-in-c)
Title: Re: Check Gmail using C#
Post by: wraith808 on October 01, 2010, 11:21 AM
If you click the plain text link, it will convert it to plain text.

As for a code sample:

Code: C# [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.IO;
  10. using UtilsLib;
  11.  
  12. namespace MyFTP
  13. {
  14.     public class Downloader
  15.         {
  16.                 private bool DownloadFile()
  17.                 {
  18.                         var ftpMyFile = new UtilsLib.SimpleFTP
  19.                         {
  20.                             LocalFilePath = "C:\",
  21.                             LocalFileName = "localFile.jpg",
  22.                             URI = "mysite.com",
  23.                             UserId = "myName",
  24.                             Password = "myPass",
  25.                             RemoteFileName = "myfile.jpg",
  26.                             UseBinaryMode = true
  27.                         };
  28.  
  29.                         bool ftpResult = ftpMyFile.InitiateTransfer(OnFTPProgress, OnFTPStart, OnFTPFinish);
  30.                         return ftpResult;
  31.                 }
  32.  
  33.                 public void OnFTPFinish(bool ftpSuccessful, string message)
  34.                 {
  35.                         if (!(ftpSuccessful))
  36.                         {
  37.                                 // Do whatever you want if the ftp is unsuccessful
  38.                         }
  39.                         else
  40.                         {
  41.                                 // Do whatever you want if the ftp is successful
  42.                         }
  43.                 }
  44.  
  45.                 public void OnFTPStart(string message)
  46.                 {
  47.                         // for reporting of progress - called when the FTP starts
  48.                 }
  49.  
  50.                 public void OnFTPProgress(int bytesTransferred, string message)
  51.                 {
  52.                         // do whatever updating of progress that you want to do
  53.                 }
  54.         }
  55. }
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 01, 2010, 01:08 PM
Awesome, Wraith!  Thanks!!

I'll share my own cool discovery:


I run a roleplaying game on www.myth-weavers.com at http://www.myth-weavers.com/forumdisplay.php?f=11199

I've been developing an application for my players that will allow them to create a new character and submit it to me, their Game Master, as an email attachment, for my perusal and approval.  In thinking ahead to the Game Master application I'll be creating at some point, one of the functions I want it to have is that it automatically checks my Gmail account when the application starts, to see if any players have emailed me any character files.

Well, I've experimented until I found a way to do this.

The following brief code snippet is simply proof of concept.  It uses the free ImapX DLL (http://hellowebapps.com/wp-content/uploads/2010/07/ImapX_1.2.3.126.zip).  In my example below, I set a Subject Line to look for that signals my program I've found the right email (in this case "myflag").  Then, it looks through my Gmail emails until it finds such an email, and downloads the email itself as a *.eml file, and saves the first attachment to the same directory.

This snippet is very crude, but could be refined to download all attachments (if there are more than one).  I could build in error-checking to ensure there IS an attachment before trying to save it to file, etc.

            ImapX.ImapClient client = new ImapX.ImapClient("imap.gmail.com", 993, true);
            bool result = client.Connection();
            if (result) {
                result = client.LogIn("[email protected]", "myPassword");
                if (result) {
                    ImapX.FolderCollection folders = client.Folders;
                    foreach (ImapX.Message m in client.Folders["INBOX"].Messages)
            {
              m.Process();                   
                      if (m.Subject == "myflag") {
                          string path = Application.StartupPath + "\\email\\";
                          string filename = "myEmail";
                          m.SaveAsEmlToFile(path, filename);
                          m.Attachments[0].SaveFile(path);
                      }
            }
                }
            }
            else {
                MessageBox.Show("connection failed");
            }

Title: Re: Check Gmail using C#
Post by: kyrathaba on October 02, 2010, 07:56 AM
Improved code-listing:

Snipplr code snippet (http://www.snipplr.com/view/41358/check-gmail-using-imapxdll/)

Code: C# [Select]
  1. /* Required for this example:
  2.              *
  3.              * a C# WinForms application
  4.              * add reference to ImapX.dll available here:
  5.              * http://hellowebapps.com/wp-content/uploads/2010/07/ImapX_1.2.3.126.zip
  6.              * http://dl.dropbox.com/u/12124382/ImapX.zip
  7.              * a button <button1>
  8.              * a textbox <textBox1>
  9.              *
  10.              * Notes: I used a very specific Subject line as my search criteria, but you need not do this.  You could
  11.              * just as easily have your code search through and download each and every email and/or every email's attachments.
  12.              */
  13.  
  14.  
  15.             ImapX.ImapClient client = new ImapX.ImapClient("imap.gmail.com", 993, true);
  16.             bool result = client.Connection();
  17.             if (result) {
  18.                 result = client.LogIn("[email protected]", "mypassword");
  19.                 if (result) {
  20.                     textBox1.AppendText(Environment.NewLine + Environment.NewLine + "Log-on successful" +
  21.                         Environment.NewLine + Environment.NewLine);
  22.                     ImapX.FolderCollection folders = client.Folders;
  23.                     foreach (ImapX.Message m in client.Folders["INBOX"].Messages)
  24.                         {
  25.                           m.Process();
  26.  
  27.                       if (m.Subject == "test email with 3 attachments (txt, png, wav)") {
  28.                           textBox1.AppendText(Environment.NewLine + Environment.NewLine + "Found email in question..." +
  29.                               Environment.NewLine + Environment.NewLine);
  30.                           string path = Application.StartupPath + "\\email\\";
  31.                           string filename = "TxtPngWav";
  32.                           //comment-out following line if you don't want to d/l the actual email
  33.                           m.SaveAsEmlToFile(path, filename);
  34.                           //use above line, and comment out the following if(){}, if you prefer to download the whole
  35.                           //email in .eml format
  36.                           if (m.Attachments.Count > 0) {
  37.                               for (int i = 0; i < m.Attachments.Count; i++) {
  38.                                   m.Attachments[i].SaveFile(path);
  39.                                   textBox1.AppendText("Saved attachment #" + (i + 1).ToString());
  40.                                   textBox1.AppendText(Environment.NewLine + Environment.NewLine);
  41.                               }
  42.                           }                          
  43.                       }
  44.                         }
  45.                 }
  46.             }
  47.             else {
  48.                 textBox1.AppendText("connection failed");
  49.             }
Title: Re: Check Gmail using C#
Post by: mouser on October 02, 2010, 07:59 AM
nice.
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 11, 2010, 09:43 PM
And since I've shown how to check Gmail using C# and Gmail's IMAP, the following snippet shows how to send an email programmatically, through your Gmail account, using C# and Gmail's SMTP.  Please note that, although the code doesn't require notification to the user that an email is about to be sent, you should always notify the end-user of your program, and give him/her the option of whether or not to send the email.  If you don't, their firewall or protective software may scare them when it pops up a message about your program attempting to send email.

Notes:

(1) your namespace's using section should include the following:
using System.Net.Mail;

(2) my example code places the email-sending code in a Button's Click() event-handler

Code: C# [Select]
  1. private void button1_Click(object sender, EventArgs e) {
  2.             DialogResult dr = MessageBox.Show("Send email?", "Get Permission", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
  3.                 MessageBoxDefaultButton.Button2);
  4.  
  5.             if (dr == DialogResult.Yes) {
  6.  
  7.                 SmtpClient smtpClnt = new SmtpClient("smtp.gmail.com", 587);
  8.  
  9.                 try {
  10.  
  11.                     MailMessage oMail = new MailMessage();
  12.                     oMail.To.Add(new MailAddress("[email protected]"));
  13.                     oMail.From = new MailAddress("[email protected]");
  14.                     oMail.IsBodyHtml = true;
  15.                    
  16.                     oMail.Body = "your message body goes here";
  17.                     oMail.Subject = "your subject goes here";
  18.  
  19.                     smtpClnt.Timeout = 100000;
  20.  
  21.                     smtpClnt.EnableSsl = true;
  22.                     System.Net.NetworkCredential nc = new System.Net.NetworkCredential("[email protected]", "your_password");
  23.                     smtpClnt.Credentials = nc;
  24.  
  25.                     Attachment oAttached = new Attachment("C:\\yourimage.jpg");
  26.                     oMail.Attachments.Add(oAttached);
  27.  
  28.                     smtpClnt.SendCompleted += new SendCompletedEventHandler(MailDeliveryComplete);
  29.  
  30.                     smtpClnt.SendAsync(oMail, "sending");
  31.  
  32.                 }
  33.                 catch (Exception mailExc) {
  34.                     if (mailExc.ToString().IndexOf("could not be resolved") >= 0) {
  35.                         int line = mailExc.ToString().IndexOf("line");
  36.                         int leng = mailExc.ToString().Length;
  37.                         string sLin = mailExc.ToString().Substring(line, (leng - line));
  38.                         string s = "Either the developer's Gmail SMTP was unavailable, or else your computer is not currently ";
  39.                         s += "connected to the internet.  Error generated at source code " + sLin;
  40.                         MessageBox.Show(s, "Unable to send character file via email");
  41.                     }
  42.                     else {
  43.                         MessageBox.Show("Error:" + Environment.NewLine + Environment.NewLine +
  44.                             mailExc.Message + Environment.NewLine + Environment.NewLine + mailExc.ToString());
  45.                     }
  46.                 }
  47.                 finally {
  48.  
  49.                     //don't invoke smtpClnt.Dispose() here; if you do, the mail never sends
  50.                 }          
  51.  
  52.  
  53.             }
  54.         }
  55.  
  56.  
  57.  
  58.         private void MailDeliveryComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e) {
  59.  
  60.             string myMessage = e.ToString();
  61.             string myCaption = string.Empty;
  62.  
  63.             if (e.Error != null) {
  64.                 myCaption = "Error sending email";
  65.             }
  66.             else if (e.Cancelled) {
  67.                 myCaption = "Sending of email cancelled.";
  68.             }
  69.             else {
  70.                 myCaption = "Your email message was sent successfully to the Game Master.";
  71.             }
  72.  
  73.             MessageBox.Show(myMessage, myCaption);
  74.  
  75.         }
Title: Re: Check Gmail using C#
Post by: mouser on October 11, 2010, 09:44 PM
cool  :up:
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 11, 2010, 09:50 PM
Made some modifications in the snippet above, for sake of clarity.  Users please note: it may not be a good idea to use a MessageBox to alert the user of your program to the success/failure of the email sending attempt (then again, that may be exactly what you want).
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 12, 2010, 12:40 PM
If anyone is reading these posts and knows the answer to the following questions, let me know:

How does one programmatically monitor and show the end-user, via a progress bar, the progress as a large email (say, a couple of large attachments) is sent?  The way Outlook Express and Outlook do.

How does one programmatically delete a Gmail message from the Inbox (by removing its "INBOX" label, for instance).
Title: Re: Check Gmail using C#
Post by: wraith808 on October 12, 2010, 01:17 PM
If you look in your code at line 28, you have a delegate added for what to do when the process completes.  Hopefully, there is also a delegate for progress; you'd add your progress bar actions in that delegate.  You'll also need to check invokerequired on whatever UI elements that you are updating, as it's possible that it will be on a separate thread.

As for the delete, I'm not sure- you'd probably have to check the library that you're using to see how to do that.
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 12, 2010, 05:32 PM
Unfortunately, the library is offered "as-is"; no documentation whatsoever, so far as I've been able to find.
Title: Re: Check Gmail using C#
Post by: wraith808 on October 12, 2010, 07:13 PM
Isn't it open source?  If not, you could take a look at http://www.codeproject.com/KB/IP/imaplibrary.aspx.  I haven't tried it, but the source is there.  Or http://xemail-net.sourceforge.net/.  Maybe they'll have support for callback delegates.
Title: Re: Check Gmail using C#
Post by: kyrathaba on October 14, 2010, 09:22 PM
I'll check into it
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 03, 2010, 01:16 PM
Hmm, it seems that I cannot get a file to upload to my website, using C#.  Here's my code (note: the only substitutions made here are that I've substituted "my_username" for my actual website username, and "my_password" for my actual password to the website):

I keep getting a 404: not found error.

Code: C# [Select]
  1. private void button1_Click(object sender, EventArgs e) {
  2.             WebClient client = new WebClient();
  3.             client.Credentials = new System.Net.NetworkCredential("my_username", "my_password",
  4.                 @"http://www.glensforkumc.com");
  5.             client.UploadFile("http://www.glensforkumc.com/non_church/myfile.txt", "localFile.txt");
  6.         }
Title: Re: Check Gmail using C#
Post by: worstje on December 03, 2010, 02:59 PM
Well, HTTP does not support file uploads in the way FTP just lets you upload a file to a location.

There are forms you can submit that can contain a file upload, but that is not the same thing as that requires a script on the other side to interpret and do with it whatever needs doing. Likewise, unless you use HTTP authentication, that credential method probably wouldn't work as most sites tend to rely on a cookie-based solution

So, depending on your situation, you might have to change your approach to either ftp, or a more involved script-based solution.
Title: Re: Check Gmail using C#
Post by: Stoic Joker on December 03, 2010, 03:35 PM
does this help any?

http://www.codeproject.com/Articles/72232/Csharp-File-Upload-with-form-fields-cookies-and-he.aspx

I bing'ed it.
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 03, 2010, 04:14 PM
Tried the code shown in the screenshot, with the resultant error (note: I'm trying to upload file "UploadDownload.pdb" that resides in the application directory of my C# app.  I want to upload it to the following directory:

http://www.glensforkumc.com/non_church/

I expected an error about not supplying a username and password (which should be required), but I'm getting the following:

[ You are not allowed to view attachments ]
Title: Re: Check Gmail using C#
Post by: Stoic Joker on December 03, 2010, 05:23 PM
Hm... I don't usually work in C# (yes that's a disclaimer) But in the code samples I saw online polking around, I got the impression that the filename needs to be added to the target url so it knows where to put it. Something like this:

Client.UploadFile("http://www.glensforkumc.com/non_church/"+FileName)

Also if IIS is configured to allow anonymous access, you're never gonna get asked for a password. Thy breaking the project into seperate chunks. (Temporarily) Allow anonymous write access to the target directory, set the NTFS permissions to allow it also, and then try uploading the file.

Also make sure you pick a small file to start/test with because IIS has default size/time limits that tend to bite.
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 03, 2010, 06:44 PM
Hmm, yeah, I can see why some of the examples would lead you to think that a concatenation is called for; however, there's no overload of the method that takes a single argument:

[ You are not allowed to view attachments ]
Title: Re: Check Gmail using C#
Post by: wraith808 on December 03, 2010, 09:42 PM
I'd take a look at the comment provided by worstje.

If you really have to use http, then you can write the file to the request stream, or emulate a post as to a form.  I've not really done either of these (only using ftp), but a quick search came up with this topic (http://stackoverflow.com/questions/1131425/send-a-file-via-http-post-with-c).
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 04, 2010, 09:51 AM
Thanks, guys.  Following up on your links and doing some reading, I've discovered it seems inordinately involved to accomplish what I'm wanting to do with http.  I'll keep researching this.  I have the following domain, which I've had for the past 18 months:

http://www.glensforkumc.com

It's a church website, but I pay for the space personally, and reserve the "non_church" subdirectory for my own use (hey, we've got 600 GB of storage, and after 18 months of use we've only used about 2 GB ;))

So, I have the required username and password to access the website.  I'm able to use FileZilla easily to upload files.  I realize that the difference is that FileZilla is using FTP, not HTTP.

What I'm looking for is simple code (no more than a few lines) to upload a local file to a specified subdirectory on the website.  I'll continue reading from the posts you linked to, and thanks!
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 04, 2010, 09:58 AM
Used this FTP code, but got the error shown below:

Code: C# [Select]
  1. string FTPAddress = "ftp://glensforkumc.com/non_church";
  2.             FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(FTPAddress + "/UploadDownload.pdb");
  3.  
  4.             request.Method = WebRequestMethods.Ftp.UploadFile;
  5.             request.Credentials = new NetworkCredential(username, password);
  6.             request.UsePassive = true;
  7.             request.UseBinary = true;
  8.             request.KeepAlive = false;
  9.  
  10.             FileStream stream = File.OpenRead("UploadDownload.pdb");
  11.             byte[] buffer = new byte[stream.Length];
  12.  
  13.             stream.Read(buffer, 0, buffer.Length);
  14.             stream.Close();
  15.  
  16.             try {
  17.                 Stream reqStream = request.GetRequestStream();
  18.                 reqStream.Write(buffer, 0, buffer.Length);
  19.                 reqStream.Close();
  20.             }
  21.             catch (Exception ex) {
  22.                 MessageBox.Show(ex.Message);
  23.             }

[ You are not allowed to view attachments ]
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 04, 2010, 08:10 PM
I spent some time this afternoon experimenting.  Hacked out this code that seems to work (see class code-listing below).  Note: allows uploading to specific directory on your website, downloading from a specific directory to a specific local directory, and has ability to return a list of files found in the root of any directory.  I also posted a copy of the code on my DC C# Errata (http://kyrathaba.dcmembers.com/errata/ftp.htm).

Code: C# [Select]
  1. public class FTPClient {
  2.  
  3.         // The hostname or IP address of the FTP server
  4.         private string _remoteHost;
  5.  
  6.         // The remote username
  7.         private string _remoteUser;
  8.  
  9.         // Password for the remote user
  10.         private string _remotePass;
  11.  
  12.         public FTPClient(string remoteHost, string remoteUser, string remotePassword) {
  13.             _remoteHost = remoteHost;
  14.             _remoteUser = remoteUser;
  15.             _remotePass = remotePassword;
  16.         }
  17.  
  18.         public string DirectoryListing() {
  19.             FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost);
  20.             request.Method = WebRequestMethods.Ftp.ListDirectory;
  21.             request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  22.             FtpWebResponse response = (FtpWebResponse)request.GetResponse();
  23.             Stream responseStream = response.GetResponseStream();
  24.             StreamReader reader = new StreamReader(responseStream);
  25.  
  26.             string result = string.Empty;
  27.  
  28.             while (!reader.EndOfStream) {
  29.                 result += reader.ReadLine() + Environment.NewLine;
  30.             }
  31.  
  32.             reader.Close();
  33.             response.Close();
  34.             return result;
  35.         }
  36.  
  37.  
  38.  
  39.  
  40.         public string DirectoryListing(string folder) {
  41.             FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + folder);
  42.             request.Method = WebRequestMethods.Ftp.ListDirectory;
  43.             request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  44.             FtpWebResponse response = (FtpWebResponse)request.GetResponse();
  45.             Stream responseStream = response.GetResponseStream();
  46.             StreamReader reader = new StreamReader(responseStream);
  47.  
  48.             string result = string.Empty;
  49.  
  50.             while (!reader.EndOfStream) {
  51.                 result += reader.ReadLine() + Environment.NewLine;
  52.             }
  53.  
  54.             reader.Close();
  55.             response.Close();
  56.             return result;
  57.         }
  58.  
  59.  
  60.         public void Download(string file, string destination) {
  61.             FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + file);
  62.             request.Method = WebRequestMethods.Ftp.DownloadFile;
  63.             request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  64.             FtpWebResponse response = (FtpWebResponse)request.GetResponse();
  65.             Stream responseStream = response.GetResponseStream();
  66.             StreamReader reader = new StreamReader(responseStream);
  67.  
  68.             StreamWriter writer = new StreamWriter(destination);
  69.             writer.Write(reader.ReadToEnd());
  70.  
  71.             writer.Close();
  72.             reader.Close();
  73.             response.Close();
  74.         }
  75.  
  76.  
  77.  
  78.         public void UploadFile(string FullPathFilename) {
  79.             string filename = Path.GetFileName(FullPathFilename);
  80.  
  81.             FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
  82.             request.Method = WebRequestMethods.Ftp.UploadFile;
  83.             request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  84.  
  85.             StreamReader sourceStream = new StreamReader(FullPathFilename);
  86.             byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
  87.  
  88.             request.ContentLength = fileContents.Length;
  89.  
  90.             Stream requestStream = request.GetRequestStream();
  91.             requestStream.Write(fileContents, 0, fileContents.Length);
  92.  
  93.             FtpWebResponse response = (FtpWebResponse)request.GetResponse();
  94.  
  95.             response.Close();
  96.             requestStream.Close();
  97.             sourceStream.Close();
  98.         }
  99.  
  100.  
  101.  
  102.     }
Title: Re: Check Gmail using C#
Post by: wraith808 on December 06, 2010, 08:52 AM
So, that still doesn't explain why you can't use ftp?  Or is it just that you don't want to?

UPDATE: nevermind... didn't see your last posts :)
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 26, 2010, 02:35 PM
RESOLVED (see my next post).

An interesting issue has arisen in a project I'm working on:

I've created the "C:/[User]/AppData/Roaming/Kyrathaba/ExcuseManager/" subdirectory programmatically, using:

Directory.CreateDirectory()

So far, so good.

But then, using my Imap code (http://www.snipplr.com/view/41358/check-gmail-using-imapxdll/), I try to download email attachments to the above directory, and I get an Unauthorized Access Expression.  Funny, because it just let me create the directory, but it now won't let me download anything to it.

The code referenced by the link above works, if you just create a default Windows Forms project in C#.  Must have something to do with the fact that I'm trying to write a binary file into a subdirectory of /[User]/; must be upsetting UAC or something, because I am able to write simple text files to the directory.  

Any ideas what's going on?
Title: Re: Check Gmail using C#
Post by: f0dder on December 26, 2010, 02:52 PM
Hmm.

1) how are you creating the above folder?
2) what kind of app is it, and how is it deployed?

I haven't had to deal with this myself yet, but I guess you might have to look at the SecurityPermissionAttribute stuff. Hopefully there's some help around here (http://msdn.microsoft.com/en-us/library/aa288469%28v=vs.71%29.aspx) :)
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 26, 2010, 02:53 PM
Figured it out: I wasn't adding a filename and extension to the end of the filename I tried to build.  DUH and DOUBLE-DUH!
Title: Re: Check Gmail using C#
Post by: kyrathaba on December 26, 2010, 02:59 PM
@fodder:  Thanks for being willing to take time and try to help.  Turns out there isn't a problem, except me being inattentive.

If you can programmatically create a subdirectory, you can write a file there, as you'd expect.
Title: Re: Check Gmail using C#
Post by: f0dder on December 26, 2010, 03:03 PM
Turns out there isn't a problem, except me being inattentive.
Bugs happen ^_^

If you can programmatically create a subdirectory, you can write a file there, as you'd expect.
Well, it's definitely what you'd expect - I was guessing that perhaps the IMAP library was running with more paranoid security settings or something. I should really find the time to read properly about .NET security.
Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 02:21 PM
I have the following functioning code to upload programmatically via FTP in C#:

Code: C# [Select]
  1. public void UploadFile(string FullPathFilename) {
  2.             string filename = Path.GetFileName(FullPathFilename);
  3.  
  4.             try {
  5.  
  6.                 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
  7.                 request.Method = WebRequestMethods.Ftp.UploadFile;
  8.                 request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  9.  
  10.                 StreamReader sourceStream = new StreamReader(FullPathFilename);
  11.                 byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
  12.  
  13.                 request.ContentLength = fileContents.Length;
  14.  
  15.                 Stream requestStream = request.GetRequestStream();
  16.                 requestStream.Write(fileContents, 0, fileContents.Length);
  17.  
  18.                 FtpWebResponse response = (FtpWebResponse)request.GetResponse();
  19.  
  20.                 response.Close();
  21.                 requestStream.Close();
  22.                 sourceStream.Close();
  23.  
  24.             }
  25.             catch (Exception ex) {                
  26.                 MessageBox.Show(ex.Message, "Upload error");
  27.             }
  28.             finally {
  29.  
  30.             }

Now for the problem.  When I use this method in the following button click event, it does upload the file to the desired directory of my website, but then my UI hangs.  I have to kill the program from within the IDE.

Code: C# [Select]
  1. private void btnUploadTxtFile_Click(object sender, EventArgs e) {
  2.  
  3.             string username = "my_username";
  4.             string password = "my_password";
  5.             string host = "ftp://glensforkumc.com";
  6.  
  7.             try {
  8.                 clsFTPclient client = new clsFTPclient(host + "/httpdocs/non_church/", username, password);
  9.                 client.UploadFile(Path.GetDirectoryName(Application.ExecutablePath) + "\\myTextFile.txt");
  10.             }
  11.             catch (Exception ex) {
  12.                 MessageBox.Show(ex.Message, "Upload problem");
  13.             }
  14.         }

Doesn't hang when using a similar method to download a file.  Any idea why my UI is freezing up after a successful upload?
Title: Re: Check Gmail using C#
Post by: f0dder on January 01, 2011, 02:40 PM
Have you tried tracing the UploadFile method in the VS debugger to see if there's any particular line of code that causes a hang?

It's not a good idea doing stuff like this from your UI thread, anyway... you should either schedule the task on a background worker thread, or (better) use Async I/O. I'll refrain from saying anything about having non-ui code in a btnWhatever_Click handler :)
Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 02:49 PM
Good points, all.  I was just doing a quick and dirty test of the UploadFile method is all.  In a full-blown application, I'd have the btnWhatever_Click handler hand off the task to a backgroundWorker object.

Maybe I'll create one and see if that fixes this issue.  Although, in the current case, why does DownloadFile work without hanging the UI, but UploadFile hangs it?  Hmm...
Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 03:09 PM
Okay, my button Click event now hands the file upload off to a backgroundWorker object running on its own thread:

Code: C# [Select]
  1. private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) {
  2.             MessageBox.Show("Doing some work...");
  3.             string username = "my_username";
  4.             string password = "my_password";
  5.             string host = "ftp://glensforkumc.com";
  6.             string myLocal = Path.GetDirectoryName(Application.ExecutablePath) + "\\myTextFile.txt";
  7.             string myRemote = host + "/httpdocs/non_church/";
  8.             clsFTPclient client = new clsFTPclient(host + "/httpdocs/non_church/", username, password);
  9.             client.UploadFile(Path.GetDirectoryName(Application.ExecutablePath) + "\\myTextFile.txt");
  10.  
  11.         }
  12.  
  13.         private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
  14.  
  15.             MessageBox.Show("I'm done uploading");
  16.         }

The file does get uploaded, but my RunWorkerCompleted() messageBox never pops up... remove everything except the messageBox from the _DoWork() method above, and it's msgBox (as well as RunWorkerCompleted's msgBox) both fire as expected.
Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 04:26 PM
Interesting.  The second MessageBox never gets invoked.  At least, I never see it pop up when I run the program click my button to upload the file:

Code: C# [Select]
  1. public void UploadFile(string FullPathFilename) {
  2.             string filename = Path.GetFileName(FullPathFilename);
  3.  
  4.             try {
  5.  
  6.                 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
  7.                 request.Method = WebRequestMethods.Ftp.UploadFile;
  8.                 request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
  9.  
  10.                 StreamReader sourceStream = new StreamReader(FullPathFilename);
  11.                 byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
  12.  
  13.                 request.ContentLength = fileContents.Length;
  14.  
  15.                 Stream requestStream = request.GetRequestStream();
  16.                 requestStream.Write(fileContents, 0, fileContents.Length);
  17.  
  18.                 MessageBox.Show("About to make upload request..."); //this one "pops-up", as expected
  19.                 FtpWebResponse response = (FtpWebResponse)request.GetResponse(); //does get invoked (my file DOES get uploaded)
  20.                 MessageBox.Show("Made upload request.  About to close streams..."); //I never see this one
  21.  
  22.                 response.Close();
  23.                 requestStream.Close();
  24.                 sourceStream.Close();
  25.  
  26.             }
  27.             catch (Exception ex) {                
  28.                 MessageBox.Show(ex.Message, "Upload error");
  29.             }
  30.             finally {
  31.  
  32.             }
  33.  
  34.         }
Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 04:48 PM
I'll be scratching my head over this one for a while, but it all works as expected now; no inexplicable hanging (even when doing the upload on its own asynch thread, it had 'seemed' to be hanging, in that I got a non-responsive UI):

Title: Re: Check Gmail using C#
Post by: kyrathaba on January 01, 2011, 07:10 PM
I've updated my Snipplr posting here (http://www.snipplr.com/view/45306/c-ftp-upload--download/).