Blog alskare

.Net y lo que surja

Añadir firma en Outlook programáticamente

Posted by alskare en 09/11/2009

La inserción de elementos que se añadan al final de nuestros mensajes en Outlook es una tarea realmente sencilla, puesto que bastará con acudir, desde el propio Outlook al menú Herramientas, Opciones, Formato de correo y “trastear” un poco con el apartado de Firma.

No obstante, en una de las empresas en las que trabajo se me ha encargado la tarea de configurar a todos los usuarios una firma estándar para todos los mensajes salientes de Outlook. Debo advertir que en esta empresa no existe ningún tipo de servidor del tipo Exchange, es más, los usuarios van conectando de modo automático a una serie de servidores POP3/IMAP de los que van descargando todos los mensajes. Con estas condiciones, sólo me quedan un par de caminos a seguir: o consigo realizar algún tipo de “distribución” de las firmas con alguna directiva de sistema o me tocará añadir, a mano, las firmas de todos los usuarios. No es que sean muchos usuarios, pero a la veintena sí que llegan y, la verdad, ante cualquier cambio, prefiero encontrar la manera más cómoda de hacerlo.

Si a estos prolegómenos le añadimos que algún usuario entra al sistema bien sea mediante Terminal Server o bien mediante la red de la oficina, hecho que provoca que se desactive la firma aunque esté, casi reconozco que no me queda otro remedio que intentar encontrar algún tipo de solución “programática” para el cambio de la firma. Nunca he sabido la causa de la desactivación de la firma, aunque en algún foro he leído que puede ser consecuencia de tener Word como editor del correo de Outlook, pero cualquiera les quita el corrector ortográfico a la gente… (si con él puesto ya te escriben hortografía, ni me imagino cómo sería sin él).

Uno de las primera cosas que más me llama la atención con el tema de las firmas es que, como Outlook permite crear mensajes en tres tipos de formato distintos, cada formato podría tener una firma diferente. Todo depende de qué opción tengamos seleccionada en Herramientas, Opciones, Formato de correo: HTML, Texto enriquecido (formato RTF) o Texto sin formato (ASCII). Por tanto empiezo creando tres ficheros con el mismo nombre, adecuando el formato a cada una de las tres opciones:

  • MiFirma.htm
  • MiFirma.rft
  • MiFirma.txt

Ubicación de las firmas

Con alguna que otra “trampilla” logro descubrir que Outlook tiene un lugar especial en el que almacena las firmas y que éste lugar depende de la versión de Outlook, así, resumo las carpetas de almacenaje en la tabla siguiente:

Versión Carpeta
O2003 \Documents and Settings\%USERNAME%Datos de programa\Microsoft\Signatures
O2007 \Documents and Settings\%USERNAME%Datos de programa\Microsoft\Firmas

¡Cómo me divierten este tipo de cambios!. Ahora resulta que tendremos que mirar la versión del usuario antes de empezar a hacer nada… Bueno, vamos a empezar a copiar los ficheros en dichas carpetas.

Un pequeño apunte para usuarios de Outlook 2003 que quieran añadir imágenes en la firma. Por un lado, las imágenes podrían estar almacenadas en una carpeta /images, justo a continuación de las rutas mencionadas en la tabla anterior y, para hacer insertar dichas imágenes, bastará con referenciarlas como src=”images/nombreImagen.jpg”, Además, deberemos acudir a Herramientas, Opciones, Formato de Correo, Formato de Internet y activar la opción Si un mensaje HTML contiene imágenes ubicadas en Internet, envíe una copia de las mismas en vez de la referencia de su ubicación.

Establecimiento de la firma

Este es el apartado más peliagudo de todo el proceso puesto que, una vez copiados los ficheros de las firmas, de forma manual sería sencillo seguir los pasos indicados al principio (Herramientas, Opciones, Formato de Correo y seleccionar como firma la denominada MiFirma), no obstante, éste sería el paso que querría evitar. Al fin y al cabo, una copia de ficheros puedo hacerla por medio de un simple fichero batch que se ejecute una vez que entre el usuario, gracias a las GPO, pero me queda averiguar cómo podría activar esta firma a los usuarios que quiera.

En las GPO que uso, por lo menos en la versión 2003 no está incluye ningún tipo de opción que permita definir la firma que tiene activa el usuario. De alguna búsqueda extraigo algún fragmento para las directivas que, según los autores, permiten establecer esta opción, pero las pruebas que hago no son fructíferas y no sólo no me establecen ningún tipo de firma sino que desactivan la opción de poder cambiar de firma, así que me decido a buscar algún otro tipo de solución.

Vamos a jugar un poco con el registro del sistema para llevarnos una desagradable sorpresa. Las cuentas que normalmente tenemos configuradas en Outlook están “almacenadas” en la rama siguiente:

HKEY_CURRENT_USER
  \Software
    \Microsoft
      \Windows NT
        \CurrentVersion
          \Windows Messaging Subsystem
            \Profiles
              \Outlook
                \9375CFF0413111d3B88A00104B2A6676

Y, para desespero, las “reglas del juego” son las siguientes: En la clave mencionada existe una clave, concretamente la clave {ED475418-B0D6-11D2-8C3B-00104B2A6676}, que tiene un tipo de datos REG_BINARY. El primer byte del valor de esta cadena incluye un número (en mi caso, por ejemplo, es el 0b). Este dato nos informará de la cuenta que hay por defecto y que será una de las ramas de la clave del cuadro anterior. Una de las cosas buenas que le veo es que, tanto para O2003 como para O2007, es la misma rama.

 image

Así, una vez hemos podido encontrar la cuenta predeterminada en Outlook, es fácil ver existen dos claves que se refieren a la firma. Estas dos claves, por supuesto, también son valores REG_BINARY y son las siguientes:

  • New Signature
  • Reply-Forward Signature

Un poco de código C#

Debo reconocer que este punto lo escribo días más tarde que el resto del post; la razón es muy sencilla, en algún sitio he visto algún script de VisualScript que permitía el cambio requerido en el registro para el tema de las firmas, pero a la hora de intentar implementarlo, siempre me he encontrado con problemas de seguridad al escribir en el registro. Entre esto y que no soy muy ducho con el tema de VisualScript, he optado por crear una pequeña utilidad en C# que me escriba las claves que necesito.

El objetivo de la aplicación, que posteriormente ejecutaré desde las GPO de Windows Server tendrá que ser una aplicación de consola que se ejecute con un parámetro, concretamente, el nombre de la firma que se quiere “predeterminar” en Outlook. Algo así cómo :

CambiaFirma.exe MiFirma

Por tanto, echo mano de una clase que desconocía hasta el momento, pero que me ha gustado bastante, la clase Microsoft.Win32.RegistryKey, puesto que resuelve casi todos los problemas de escritura en el registro.

Muestro la clase tal cual, incluyendo una pantalla de consola que muestra el error en caso de que exista. Imagino que en la implementación final la quitaré para que, en caso de problemas no aparezca la pantallita.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;


namespace CambiaFirma
{

    /// <summary>
    /// Ejecución del programa de cambio de firma
    /// </summary>
    class CambiarFirma
    {


        /// <summary>
        /// Inicio de la aplicación. Comprobación de argumento y gestión 
        /// de la firma
        /// </summary>
        /// <param name="args">Deberá incluir un parámetro: NombreFirma</param>
        static void Main(string[] args)
        {
            try
            {
                // Lectura de parámetros para obtener el nombre de la firma
                if (args.Length != 1)
                    throw new ArgumentException("Debe añadirse el nombre de la firma como parámetro");
                string nombreFirma = args[0];

                // Gestión de firma
                GestionFirma gf = new GestionFirma(nombreFirma);
                gf.EscribeFirma();
            }
            catch (Exception ex)
            {
                MuestraError(ex);
            }
        }


        /// <summary>
        /// Muestra un error por pantalla de consola
        /// </summary>
        /// <param name="ex"></param>
        private static void MuestraError(Exception ex)
        {
            Console.Clear();
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("ERROR EN CREACIÓN DE FIRMA");
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(ex.Message);
            Console.ForegroundColor = ConsoleColor.White;

            for (int i = Console.CursorTop; i < Console.WindowHeight - 1; i++)
            {
                Console.WriteLine();
            }
            Console.Write("Pulsa una tecla para continuar ... : ");
            Console.ReadKey(true);
        }
    }



    /// <summary>
    /// Clase que añade una firma a la cuenta por defecto de Outlook
    /// </summary>
    /// <remarks>Provado en Outlook 2003 y Outlook 2007</remarks>
    class GestionFirma
    {
        private string NombreFirma { get; set; }

        /// <summary>
        /// Constructor de la clase.
        /// </summary>
        /// <param name="nombreFirma">
        /// Texto que representa la firma que se insertará en Outlook
        /// </param>
        public GestionFirma(string nombreFirma)
        {
            NombreFirma = nombreFirma;
        }

        /// <summary>
        /// Cambia el registro del sistema de manera que la firma quedará activada
        /// en Outlook
        /// </summary>
        public void EscribeFirma()
        {
            RegistryKey r = GetRamaCuentaPredeterminadaOutlook();

            byte[] firma = GetFirmaCodificada(NombreFirma);

            // Escritura de los valores
            r.SetValue("New Signature", firma);
            r.SetValue("Reply-Forward Signature", firma);
        }

        /// <summary>
        /// Obtiene la rama del registro correspondiente a la cuenta predeterminada 
        /// de Outlook
        /// </summary>
        /// <returns></returns>
        private RegistryKey GetRamaCuentaPredeterminadaOutlook()
        {
            // Lectura de la rama \\HKCU
            RegistryKey rkRaiz = Registry.CurrentUser;

            // Lectura de la rama en al que se almacena el correo
            RegistryKey rkCorreo =
                rkRaiz.OpenSubKey(
                        "Software\\Microsoft\\Windows NT"
                        + "\\CurrentVersion\\Windows Messaging Subsystem"
                        + "\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676");

            // Se obtiene el valor de la clave que contiene la cuenta predeterminada
            byte[] cuentaDefecto = (byte[])rkCorreo.GetValue(@"{ED475418-B0D6-11D2-8C3B-00104B2A6676}");

            // Se obtiene el valor de la subclave que contiene la cuenta predeterminada
            string claveCuentaDefecto = "000000" + ((byte)(cuentaDefecto.GetValue(0))).ToString("X2").ToLower();

            // Se abre la rama con la cuenta predeterminada con permisos de escritura
            RegistryKey rkCuentaDefecto = rkCorreo.OpenSubKey(claveCuentaDefecto, true);

            return rkCuentaDefecto;
        }

        /// <summary>
        /// Codifica el nombre de la firma en un array de Bytes
        /// </summary>
        /// <returns>La codificación se hace tal cómo lo hace Outlook</returns>
        private static byte[] GetFirmaCodificada(string nombreFirma)
        {
            // Codificación del nombre de la firma
            ASCIIEncoding ascii = new ASCIIEncoding();
            byte[] firmaSinCeros = ascii.GetBytes(nombreFirma);

            // La firma de Outlook contiene un byte vacío por cada byte del nombre,
            // así que incluyo un List para no complicarme la vida y añadirle los 
            // bytes vacíos.
            List<byte> firmaConCeros = new List<byte>();

            // Se añaden los ceros a la firma
            foreach (byte b in firmaSinCeros)
            {
                firmaConCeros.Add(b);
                firmaConCeros.Add(new byte());
            }

            // No sé la razón, pero la firma le añade dos bytes más
            firmaConCeros.Add(new byte());
            firmaConCeros.Add(new byte());

            return firmaConCeros.ToArray();
        }
    }

}

Ahora, con el programita éste ya puedo ejecutarlo de tal manera que, cada vez que un usuario inicie la sesión, se le establezca la firma deseada en la cuenta predeterminada de Outlook.

Confío que no me hagan establecer una firma para cada una de las cuentas que tengan configuradas en Outlook, pero con los jefes “tan listos” de las empresas, nunca se sabe…”Si total, como es algo fácil establecer la firma… ¿Ves?, sólo hay que hacer Herramientas, Opciones, Formato de correo

Como siempre, dejo enlace para descarga por si alguien no tiene el compilador o, sencillamente, no tiene ganas de hacer un Copy & Paste.

Descarga del programa: aquí

6 comentarios to “Añadir firma en Outlook programáticamente”

  1. alskare said

    Sí, es cierto. Al igual que para ejecutar cualquier aplicación creada en C# o VB.Net

  2. Pau said

    Atención para que funcione CambiaFirma.exe se debe tener instalado el MS FrameWork 2.0

  3. […] RSS Añadir firma en Outlook programáticamenteC#. Generador de Passwords aleatoriosC# Personalizar la ordenación de listas con IComparableC# […]

  4. alskare said

    Hola, Rafael.
    Me sabe mal, pero debo comentarte que soy de aquellas personas que tiene pensado dar el salto desde Windows XP a Windows 7. Vamos que, si puedo, el Vista sólo lo he utilizado para hacer alguna modificación (siempre pequeña) a algún usuario de alguna empresa. Lamento comentar que ni tal siquiera he visto hasta el momento nada de Windows Mail.

  5. Rafael Baquero said

    Estimado Alskare:

    He leído en el “Discussions in Outlook” cómo aconsejas a Jose Ignacío sobre cómo insertar la firma en Outlook. Yo llevo meses peleándome con Windows Mail (incluido en Vista) para hacer lo mismo y no lo consigo. En Outlook 2003 no tengo problema (una vez encontrado el sitio donde guardar la firma, claro), pero en el Windows Mail que viene con Vista (antiguo Outlook Express adaptado), cada vez que lo intento, al crear un nuevo mensaje de correo, me sale el aviso “Advertencia: El archivo de la firma es demasiado grande y se ha truncado. Reduzca su tamaño”. El caso es que el archivo es pequeño, está correctamente creado en HTML mediante Word y es el mismo que sí me funciona en Outlook. ¿Puedes ayudarme?
    Muchas gracias

    Rafael Baquero

  6. ancafe said

    Espectacular.

    Muchas gracias. Muy didáctico este artículo

Sorry, the comment form is closed at this time.

 
A %d blogueros les gusta esto: