• 21.04.2010 23:52:50

    Encrypted mails with C#, GPG and System.Net.Mail
    Writing encrypted emails with C Sharp
    from: cpom | Comments: 0

  • A lot of sources say you can’t send encrypted emails with System.Net.Mail from Microsofts .Net Framework. Its true, System.Net.Mail does not not come with encryption support right out of the box. Working around this, it is realy simple to achieve that with GPG and an external process that is spawned from your program, at least for plain text mails.

  • Sending encrypted emails with sensitive information is today a normal task in a company. GPG and PGP provide plugins for email clients like Thunderbird or Outlook. And it works fine if you encrpt your information manually.

    For automated task , like sending encrypted logs or automatic reports, mutt or mailx is used in shell scripts on linux and unix systems. The plain text information is piped to gpg, wich encrypts the text and pipes it to the console mail client as mail body. So, why should this not work with System.Net.Mail ?

    excerpt from a shell script using gpg for encryption

    And indeed: it is realy that simple. You start an external process, call “cmd.exe” and give it a prepared commandline with your ascii text and the gpg parameters for sender, recipient and encryption mode. After execution you can read back the resulting enrypted text (which is ascii too) from console and use it as mail body in your program.

    Preparing your gpg installation

    GPG (Gnu privacy Guard ) comes with a batch mode for automatic tasks. This batch mode is (AFAIK) meant to be used only for automatic decryption, but one can use it for encryption to. If you want to use it together for automatic signing and encryption of the mail you must break the security chain by removing the key passphrase from you key.

    To work around this you can create a second key ring only used for automatic mail encryption and signing, store it in a safe and secret location and remove the key passphrase. If you trust the recipient and he trusts you as a sender : use encryption only.

    Install GPG locally on the machine where your programm should run. You can download a special Windows version of the programm with a tools suite. This GPG4Win here. Don’t use whitespaces in the directory name of the gpg installation. It creates headaches if you later, in your program, will combine your command line for execution. Create a key only for the task you want to do or put an already existing key on your keyring. Next, put the key for the recipient(s) on the keyring. Test your installation on the shell, for example:

    echo “I write encrypted mails” | c:\gpginstalldir\gpg. exe - batch -e -a -u backup@example.org -recipient bob@example.org

    wich should result in an output like Picture2 -- an ASCII armored, enrypted message wich can only be decrypted by bob@example.org

    encrypted ascii text

    If it works, you can go ahead and write your program.

    Writing your C# code

    Now comes the easy part: writing the program code. As with unencrypted mail messages you could use System.Net.Mail.SmtpClient and System.Net.Mail.MailMessage.

    I wrote a new class (for a customer) wich extends System.Net.Mail.MailMessage and added a new public and two private methods. The public method ist called to hand over the plain text message, and fill the mail body property with the encrypted message.

    Inside this public method the two private methods are called. The first one builds the command line for gpg and the second one creates an external process and reads the text encprypted back. In the last step, the mail body property is filled with the encrypted message. If something goes wrong in the creation process, an exception will be thrown and the mail body will remain empty.

    For reading in commandline options like sender, recipient and operation mode I created a simple Datamodel , wich is a POCO (Plain Old C# Object) with the required properties and can be filled from outside, for example from the app.config or a database.

    Project layout for GpgMail

    Code Samples

    For building the commandline I use a simple string builder and append the required portions. _shellCmd is a property of my derived class.

      public void buildCommandLine(plainTextMail){
        // local var
        StringBuilder sb = new StringBuilder();
        // append the stuff
        sb.Append("echo " + plainTextMail);
        sb.Append(@" | " +Path.Combine(_encrytperModel._gpgPath,_encrytperModel._gpgExecutable));
        sb.Append(" " + _encrytperModel.GpgOptions);
        sb.Append(" -u " + _fromSender);
        sb.Append(" --recipient " + _toRecipient + "");
        // set the property
        _shellCmd = sb.ToString();

    This is the second private method, where _shellCmd is an argument list for processStartinfo. _encrytedMail is a property, which is requested when the mailbody will be filled.

      public void runGpgProcess (){
        // error list
        ArrayList gpgError = new ArrayList();
        ProcessStartInfo shellProcInfo = new ProcessStartInfo("cmd.exe");
        // prepare
        shellProcInfo.Arguments = _shellCmd;
        shellProcInfo.RedirectStandardOutput = true;
        shellProcInfo.RedirectStandardError = true;
        shellProcInfo.CreateNoWindow = false;
        shellProcInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        shellProcInfo.UseShellExecute = false;
        // start the shell process
        Process shellProc = Process.Start(shellProcInfo);
        shellProc.EnableRaisingEvents = true;
        StreamReader shellReader = shellProc.StandardOutput;
        // standard error output
        string errorOutput = shellProc.StandardError.ReadLine();
        while (errorOutput != null && errorOutput != string.Empty){
        // and read from standard output
        if (shellProc.HasExited && gpgError.Count == 0){
              _encrytedMail = shellReader.ReadToEnd();

    Adjust the settings for timing, if you feel uncomfortable with 500 ms, I guess, if your messages grow larger Thread.Sleep and shellProc.WaitForExit() should be raised to 1000 or 2000 ms


    As you see, it is very easy to write an encrypted email with System.Net.Mail. If you want to send one or more encrypted attachments use a separate shell process for each item to encrypte and add them via encryptedMail.Attachments.add(Attachment item) to yout MailMessage object.

    Some parts of this text are translated with the Google Translator from german to english

    Kommentar hinzufügen | nach oben

  • Comments are disabled

Kommentare augeschaltet






2007 - 2010 ©   Claudius Pomorska

Profi-Admin is powered by MBlog Portal