Blog alskare

.Net y lo que surja

Archive for the ‘Outlook’ Category

Gestionar cuentas de Outlook desde C#

Posted by alskare en 06/12/2009

Tras haberme peleado un tiempo con el tema de poder configurar la firma de Outlook desde una aplicación propia, tema que puede encontrarse en el post https://alskare.wordpress.com/2009/11/09/aadir-firma-en-outlook/, me quedé con las ganas de poder profundizar un poco más en el tema de cómo se gestiona el tema de las cuentas de correo en el registro del sistema, más que nada, porque estoy más que seguro que en breve necesitaré modificar no sólo la firma en la cuenta predeterminada.

Aunque la idea inicial es la de partir del artículo anterior, rápidamente me doy cuenta de alguna imprecisión cometida por mi parte. Imagino que las prisas y las ganas de acabar rápido logran que, en un primer intento, te dejes algún cabo suelto. En este caso, opto por dejar el artículo anterior tal cuál está y así me permitiré, desde aquí, realizar todas las correcciones o anotaciones que considere necesarias.

Una clave del registro controla las cuentas

La principal imprecisión a la que me refería es cuando indicaba que el primer byte de una determinada clave del registro “apuntaba” a la dirección de la cuenta por defecto. Después de haber intentado algún cambio en mi propio ordenador, casi me quedo sin poder entrar en Outlook al producir un error nada más entrar.

– ¿Qué has hecho para poder provocar este error?.
– Casi nada, tan sólo cambiar directamente, desde el registro, el primer byte que se muestra (el de la cuenta predeterminada) por el de otra cuenta válida
– Así, ¿sin más?. ¿Qué ha ocurrido?
– Poca cosa. No me di cuenta que el valor de dicha entrada no es un byte, son 4 bytes en formato Little Endian. Y además, esta misma clave contiene el orden en el que se encuentran las cuentas de correo. Fíjate en el ejemplo siguiente, mi cuenta por defecto es la que está en la clave 0000000b, la siguiente cuenta en la lista de Outlook es la 00000005 y así sucesivamente.

 registro

– ¿has conseguido arreglarlo?.
– Siempre que toco el registro, hago antes una copia de la rama (menos mal que no le digo que he tenido que descubrir lo del Litte Endian porque no conseguía entrar en Outlook)

Lectura de las cuentas configuradas

Una vez que conocemos tanto la cuenta predeterminada como el resto de cuentas de Outlook, tan sólo nos hace falta hacer una lectura de las mismas, así que empezamos creando una lectura, precisamente de los nombres de las cuentas.

/// <summary>
/// Obtiene una lista con las claves de las cuentas de Outlook
/// </summary>
/// <returns></returns>
public string[] getOutlookAccounts()
{
    RegistryKey rkRaiz = Registry.CurrentUser;

    string ramaCuentas =
          "Software\\Microsoft\\Windows NT"
           + "\\CurrentVersion\\Windows Messaging Subsystem"
           + "\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676";

    List<string> listaCuentas = new List<string>();
    RegistryKey rkCuentas = rkRaiz.OpenSubKey(ramaCuentas);

    // Lectura del valor que contiene las cuentas de Outlook
    object oCuentas = rkCuentas.GetValue("{ED475418-B0D6-11D2-8C3B-00104B2A6676}");
    if (oCuentas != null && oCuentas.GetType().Equals(typeof(byte[])))
    {
        byte[] cuentas = (byte[])oCuentas;
        for (int i = 0; i < cuentas.Length; i += 4)
        {
            // Traspaso de Little Endian a Big Endian
            StringBuilder sb = new StringBuilder();
            sb.Append(((byte)(cuentas.GetValue(i + 3))).ToString("X2").ToLower());
            sb.Append(((byte)(cuentas.GetValue(i + 2))).ToString("X2").ToLower());
            sb.Append(((byte)(cuentas.GetValue(i + 1))).ToString("X2").ToLower());
            sb.Append(((byte)(cuentas.GetValue(i))).ToString("X2").ToLower());

            listaCuentas.Add(sb.ToString());
        }
    }
    return listaCuentas.ToArray();
}

Leer información de una cuenta

Una vez tenemos una lista con las cuentas de correo existentes, podemos empezar a pensar en cómo extraer la información de cada una de las cuentas. Para ello, nos creamos una clase auxiliar para poder almacenar la información.

namespace jnSoftware.Outlook.Accounts
{

    /// <summary>
    /// Clase que representa una cuenta de correo de Outlook en el registro
    /// </summary>
    public class MailAccount
    {

        /// <summary>
        /// Obtiene el orden en el que se encuentra la cuenta de correo en la lista de
        /// Outlook
        /// </summary>
        public int OrderList { get; internal set; }


        /// <summary>
        /// Obtiene el nombre de la clave que contiene la información de la cuenta en 
        /// el registro
        /// </summary>
        public string AccountID { get; internal set; }


        /// <summary>
        /// Obtiene un valor que indica si la cuenta es la predeterminada
        /// </summary>
        public bool IsDefaultAccount
        { get { return OrderList == 0; } }


        /// <summary>
        /// Obtiene la cuenta de correo asociada a la cuenta
        /// </summary>
        public string Email { get; internal set; }


        /// <summary>
        /// Obtiene el nombre de la cuenta de correo.
        /// </summary>
        public string AccountName { get; internal set; }


        /// <summary>
        /// Obtiene el valor establecido como firma para nuevos mensajes
        /// </summary>
        public string NewSignature { get; internal set; }


        /// <summary>
        /// Obtiene el valor establecido como firma para los mensajes que 
        /// se responden
        /// </summary>
        public string ReplySignature { get; internal set; }
             
    }
}

A partir de ahora, la imaginación al poder. Además de los métodos que se nos pueden ocurrir en un primer momento, la verdad es que, pensando un poco en detalle, las posibilidades son amplias. Incluyamos algún ejemplo:

  • Obtener una lista con la información de todas las cuentas
  • Obtener información de una cuenta concreta (por Id o por cuenta de correo)
  • Obtener información de la cuenta de correo predeterminada
  • Cambiar la firma de una cuenta concreta (no sólo la cuenta predeterminada)

Partiendo de los puntos anteriores desarrollo una clase que permita realizar los trabajos mencionados, aunque me imagino que, en el momento que tenga un poco de tiempo acabaré creando alguna aplicación en WinForms que permita realizar estos cambios de un modo más amigable. De momento, con la librería actual se pueden realizar muchos cambios desde, por ejemplo, un inicio de sesión en una red.

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


namespace jnSoftware.Outlook.Accounts
{

    /// <summary>
    /// Gestión de cuentas de correo de Outlook
    /// </summary>
    public class MailAccounts
    {


        private Dictionary<string, MailAccount> cuentasOutlook;

        // Las cuentas de correo dependen directamente de HKCU
        private RegistryKey rkRaiz
        { get { return Registry.CurrentUser; } }

        // De la rama siguiente dependen todas las cuentas de correo definidas
        // en Outlook
        private string ramaCuentas =
               "Software\\Microsoft\\Windows NT"
                + "\\CurrentVersion\\Windows Messaging Subsystem"
                + "\\Profiles\\Outlook\\9375CFF0413111d3B88A00104B2A6676";



        /// <summary>
        /// Obtiene las cuentas de correo de Outlook definidas en el registro
        /// </summary>
        /// <returns></returns>
        public List<MailAccount> GetAccounts()
        {
            readInfoAccounts();
            return new List<MailAccount>(cuentasOutlook.Values);
        }


        /// <summary>
        /// Obtiene información de una cuenta de correo determinada
        /// </summary>
        /// <param name="accountID">Identificador de la cuenta de correo. Se corresponde 
        /// con el nombre de la rama del registro</param>
        /// <exception cref="ArgumentOutOfRangeException">Se produce la excepción cuando no 
        /// se encuentra la cuenta especificada en <paramref name="accountID"/></exception>
        public MailAccount GetAccount(string accountID)
        {
            readInfoAccounts();
            try
            {
                return cuentasOutlook[accountID];
            }
            catch (KeyNotFoundException ex)
            {
                throw new ArgumentOutOfRangeException("No existe la cuenta solicitada", ex);
            }
            catch { throw; }
        }


        /// <summary>
        /// Obtiene información de la cuenta establecida por defecto
        /// </summary>
        public MailAccount GetDefaultAccount()
        {
            string[] cuentas = getOutlookIdAccounts();
            return GetAccount(cuentas[0]);
        }


        /// <summary>
        /// Obtiene información de una cuenta de correo en base a su dirección electrónica
        /// </summary>
        /// <param name="email">Cuenta de correo de la que se quiere recuperar la información</param>
        /// <exception cref="ArgumentOutOfRangeException">Se produce cuando  no se encuentra la 
        /// cuenta de correo especificada en <paramref name="email"/>.</exception>
        public MailAccount GetAcountByEmail(string email)
        {
            readInfoAccounts();

            MailAccount retVal = null;
            // Como en la Uni, desarrollamos un algoritmo de búsqueda
            foreach (MailAccount cuenta in cuentasOutlook.Values)
            {
                if (cuenta.Email == email)
                {
                    retVal = cuenta;
                    break;
                }
            }
            if (retVal != null)
            { return retVal; }
            else { throw new ArgumentOutOfRangeException("Cuenta de correo no encontrada"); }
        }


        /// <param name="email">Cuenta de correo de la que se quiere establecer la firma</param>
        /// <param name="newSignature">Nombre de la firma que quiere establecerse en la cuenta de 
        /// correo para mensajes nuevos</param>
        /// <param name="replySignature">Nombre de la firma que quiere establecerse en la cuenta 
        /// de correo para mensajes respondidos</param>
        public void SetSignature(string email, string newSignature, string replySignature)
        {
            MailAccount cuenta = GetAcountByEmail(email);

            // TODO : Queda pendiente una comprobación para que existan las firmas 
            // en la carpeta de firmas.

            RegistryKey rkCuenta = rkRaiz.OpenSubKey(ramaCuentas + "\\" + cuenta.AccountID, true);
            rkCuenta.SetValue("New Signature", GetFirmaCodificada(newSignature));
            rkCuenta.SetValue("Reply-Forward Signature", GetFirmaCodificada(replySignature));
        }


        /// <summary>
        /// Realiza la lectura de las cuentas definidas en el registro
        /// </summary>
        private void readInfoAccounts()
        {
            cuentasOutlook = new Dictionary<string, MailAccount>();
            string[] cuentas = getOutlookIdAccounts();
            for (int i = 0; i < cuentas.Length; i++)
            {
                MailAccount m = getInfoAccount(cuentas[i]);
                m.OrderList = i;
                cuentasOutlook.Add(m.AccountID, m);
            }
        }


        /// <summary>
        /// Recupera la información de una cuenta determinada.
        /// </summary>
        /// <param name="accountID"></param>
        /// <returns></returns>
        private MailAccount getInfoAccount(string accountID)
        {
            MailAccount m = new MailAccount();
            m.AccountID = accountID;

            RegistryKey rkCuentas = rkRaiz.OpenSubKey(ramaCuentas + "\\" + accountID, false);
            m.Email = binaryToString(rkCuentas.GetValue("Email"));
            m.NewSignature = binaryToString(rkCuentas.GetValue("New Signature"));
            m.ReplySignature = binaryToString(rkCuentas.GetValue("Reply-Forward Signature"));
            m.AccountName = binaryToString(rkCuentas.GetValue("Account Name"));

            return m;
        }


        /// <summary>
        /// Obtiene una lista con las claves de las cuentas de Outlook
        /// </summary>
        /// <returns></returns>
        private string[] getOutlookIdAccounts()
        {
            List<string> listaCuentas = new List<string>();
            RegistryKey rkCuentas = rkRaiz.OpenSubKey(ramaCuentas, false);

            // Lectura del valor que contiene las cuentas de Outlook
            object oCuentas = rkCuentas.GetValue("{ED475418-B0D6-11D2-8C3B-00104B2A6676}");
            if (oCuentas != null && oCuentas.GetType().Equals(typeof(byte[])))
            {
                byte[] cuentas = (byte[])oCuentas;
                for (int i = 0; i < cuentas.Length; i += 4)
                {
                    // Traspaso de Little Endian a Big Endian
                    StringBuilder sb = new StringBuilder();
                    sb.Append(((byte)(cuentas.GetValue(i + 3))).ToString("X2").ToLower());
                    sb.Append(((byte)(cuentas.GetValue(i + 2))).ToString("X2").ToLower());
                    sb.Append(((byte)(cuentas.GetValue(i + 1))).ToString("X2").ToLower());
                    sb.Append(((byte)(cuentas.GetValue(i))).ToString("X2").ToLower());

                    listaCuentas.Add(sb.ToString());
                }
            }
            return listaCuentas.ToArray();
        }


        /// <summary>
        /// Decodifica una cadena del registro en una cadena ASCII.
        /// </summary>
        /// <param name="cadena">Cadena del registro. Devuelve string.empty si la 
        /// cadena estuviese vacía.</param>
        /// <returns></returns>
        private string binaryToString(object cadena)
        {
            StringBuilder sb = new StringBuilder();
            if (cadena != null)
            {
                if (cadena.GetType().Equals(typeof(byte[])))
                {
                    byte[] entrada = (byte[])cadena;
                    ASCIIEncoding ascii = new ASCIIEncoding();

                    // Bucle para eliminar los bytes vacíos que se colocan en el registro
                    for (int i = 0; i < entrada.Length; i++)
                    {
                        if (entrada[i] != 0)
                        {
                            sb.Append(ascii.GetString(entrada, i, 1));
                        }
                        i++;
                    }
                }
            }
            return sb.ToString();
        }


        /// <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();
        }


    }       // class
}           // namespace

 

En esta ocasión no dejo las librerías listas para la descarga puesto que así intento obligarme a crear una tercera entrega dedicada a Outlook en la que intentaré que se puedan establecer algunos cambios desde una aplicación WinForms.

Anuncios

Posted in C#, Outlook | 1 Comment »

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í

Posted in Outlook | 6 Comments »

Reparar fichero .pst de Outlook

Posted by alskare en 22/02/2009

Cada vez son más los empleados de las empresas que se empeñan en averiguar los límites de cualquier programa. En este caso, le toca el turno a Outlook. Sin saber ni conocer la razón, me encuentro día tras día con usuarios que almacenan, en las entrañas de un fichero .pst de Outlook la nada despreciable cifra de 4 Gb entre mensajes y adjuntos, muchos de ellos, las típicas bromas PowerPoint que solemos recibir unas diez o quince veces al año de gente que considera original enviar lo que le envían.

Yo no entro en discusiones acerca de si es correcto almacenar o no este tipo de información, ni tal siquiera si tiene lógica almacenar un volumen de información en un mismo fichero el cual, al fin y al cabo, no deja de ser un pequeño pero potente motor de base de datos. Tan sólo, cobro mi trabajo y, por tanto, me considero en la obligación de arreglarlo y avisar al usuario que, de seguir con estos volúmenes, igual algún día se lleva un buen susto.

Sobre todo, cuando se tienen perfiles de usuario móviles, estos volúmenes de ficheros, independientemente de la escasa celeridad de la respuesta, ocasionan algún que otro problema que suele manifestarse de diversas maneras: Bloqueo de outlook, mensajes de error informando del mal estado de la “Bandeja de Entrada” o de la necesidad de reparar la bandeja de entrada continuamente, etc.

Hasta el momento, cuando he tenido algún problema de este tipo, siempre he echado mano una herramienta que incluye Outlook y que suele instalarse en una carpeta de nuestro disco. Esta herramienta se denomina:

ScanPst.exe

ScanPst.exe se instala, por defecto, dependiendo de la versión:

Office 2003 (en español)

%ProgramFiles%\Archivos Comunes\System\MSMPAI\3082

Office 2007 (en español)

%ProgramFiles%\Microsoft Office\Office 12\

En el caso que se haya instalado el office en cualquier otra ubicación, siempre nos queda la posibilidad de buscarlo.

Una vez encontrada la aplicación, su ejecución es muy sencilla.

image

Bastará con seleccionar el nombre del fichero .pst que nos da problemas y, a partir de ahí, el botón Iniciar realizará, primero, un análisis del fichero, tras el cuál nos informará de la existencia de posibles errores. La verdad es que, casi siempre que he ejecutado la herramienta, me ha advertido de errores. Al principio, pensé que se trataba de algún problema de mi portátil, pero cuando repetí la prueba en varios ordenadores, supuse que era algo “normal” que devolviese errores. Como medida precautoria, siempre marco la opción de realizar la copia de seguridad, procurando no olvidarme después de borrar esta copia (recordemos que no es la primera vez que me he encontrado algún fichero .pst de 4 Gb).

image

Un último mensaje se encarga de avisarnos que la corrección del fichero se ha realizado satisfactoriamente.

Posted in Outlook | Comentarios desactivados en Reparar fichero .pst de Outlook