ThXou

Ama la sabiduría. Desea el conocimiento

iOS: Enviar Correo Electrónico Desde La Aplicación

| Comments


Mientras trabajaba en mi aplicación Listed quise que los usuarios pudieran enviar sus listas por correo, y la verdad pensé que iba a ser difícil de hacer pero no fue así.

Apple provee una clase llamada MFMailComposeViewController dentro del framework MessageUI que hace muy sencillo el hecho de enviar correos sin tener que salir de la aplicación siquiera, esto, a través de la misma interfaz que usas en la aplicación Mail. Además te permite definir el contenido inicial de los campos del correo y también enviar uno o varios archivos adjuntos, como también provee de funcionalidad para responder a los eventos del usuario como enviar, cancelar o guardar un mensaje de correo.

La aplicación que toca esta vez va a permitir a los usuarios enviar un correo electrónico desde la aplicación. Usando el único método del delegado MFMailComposeViewControllerDelegate, vamos a mostrar al usuario mensajes dependiendo de si el correo se ha enviado, cancelado, guardado en borradores o ha fallado en el envío.

[note]Nota:Es importante resaltar que cuando hablo de envío, me refiero a que el correo ha sido puesto en la cola de envío (carpeta de Salida en Mail), no que ya se ha enviado. Lo mismo para cuando cancelamos el envío, en realidad quiere decir que el correo no se ha puesto en la cola de envío.[/note]

Preparando el terreno

Para este proyecto he creado uno de tipo Single View Application y le he puesto de nombre ”emailMe”.

Lo primero que haremos será añadir el framework MessageUI a nuestra aplicación, luego vamos a definir un Outlet UILabel y una acción, así como también hacemos a ViewController conforme al protocolo MFMailComposeViewControllerDelegate. Para esto vamos al fichero ViewController.h y ponemos el siguiente código:

1
2
3
4
5
6
7
8
9
10
11
12
13
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>

@interface ViewController : UIViewControler <MFMailComposeViewControllerDelegate>
{
    UILabel  *estado;
}

@property (nonatomic, retain) IBOutlet UILabel *estado;

- (IBAction)enviarCorreo:(id)sender;

@end

Acto seguido pasamos a la interfaz de usuario, así que abrimos el fichero ViewController.xib y añadimos simplemente 2 objetos, uno de tipo UIButton y otro UILabel. El botón es para abrir la ventana modal desde donde escribiremos el correo y el label es para mostrar el estado del envío. Una vez añadidos, conectamos el UILabel con el código. Hacemos esto presionando la tecla Ctrl y arrastrando el cursor desde el File’s Owner hasta el objeto UILabel en el Interface Builder y luego seleccionando el correspondiente de la lista que aparece.

Implementación de la funcionalidad

Hay un método al que siempre tenemos que llamar antes de mostrar la interfaz de envío de correo, y es: canSendMail, este nos va a servir para verificar si el dispositivo del usuario está habilitado para usar esta característica. En caso contrario, yo he decidido mostrar una alerta diciendo que el dispositivo no soporta el envío de correo.

Abrimos el ViewController.m para implementar nuestro método creado anteriormente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@synthetize estado;

- (IBAction)enviarCorreo:(id)sender
{
    // verificamos si es posible enviar correo desde este dispositivo
    if ([MFMailComposeViewController canSendMail])
    {
        MFMailComposeViewController *email = [[[MFMailComposeViewController alloc] init] autorelease];

        email.mailComposeDelegate = self;

        // definimos el asunto del correo
        [email setSubject:@"Te envío una Web que mola"];

        // definimos el contenido inicial del correo
        NSMutableString *cuerpo = [[NSMutableString alloc] init];
        [cuerpo appendString:@"Hey!, he encontrado esta web y me ha gustado : )<br /><br /><a href='http://www.thxou.com'>http://www.thxou.com</a>"];

        // asignamos el cuerpo del mensaje y le decimos que lo interprete como HTML
        [email setMessageBody:cuerpo isHTML:YES];
        [cuerpo release];

        // adjuntamos una imagen desde nuestro bundle
        UIImage *imagen = [UIImage imageNamed:@"logo-thxou.png"];
        NSData *imagenData = UIImagePNGRepresentation(imagen);
        [email addAttachmentData:imagenData mimeType:@"image/png" fileName:@"thxoulogo"];

        // mostramos la ventana modal con la interfaz de envío de correo
        [self presentViewController:email animated:YES completion:nil];
    }
    else {
        // mostramos una alerta si el dispositivo no puede enviar correo
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                        message:NSLocalizedString(@"Tu dispositivo no soporta esta característica", nil)
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

Como veis es muy sencillo implementar esta funcionalidad en una aplicación, con lo poco que hemos escrito ya es posible enviar un correo, no obstante aún nos falta la parte de manipular los eventos que dije al principio.

El método setMessageBody:isHTML: como puedes observar te permite asignar un contenido inicial para el correo. Si deseas que este contenido sea interpretado como código HTML, lo haces a través etiqueta isHTML:, la cual te permite especificarlo.

Luego tenemos el método addAttachmentData:mimeType:fileName: que nos va a permitir enviar datos adjuntos al correo. El primer argumento requiere un objeto de tipo NSData, así que lo que sea que queramos enviar tiene que estar primero convertido a este tipo de datos, en mi caso el logo de la web en formato .png.

El segundo argumento (mimeType:) es el tipo MIME del archivo que vamos a enviar, esto no te lo tienes que inventar ya que es un stardard predefinido y puedes ver el tipo MIME correspondiente a tu archivo en http://www.iana.org/assignments/media-types/. El tercer argumento es simplemente el nombre que deseas que tenga el archivo cuando sea transferido a su destino. Puedes repetir este método para cada uno de los archivos que desees adjuntar.

Hay otros métodos como setToRecipients:, setCcRecipients: y setBccRecipients: que cumplen exactamente la misma función que en un correo ordinario.

Manipulando el resultado del envío

Como se puede ver en la línea 8 del código de arriba, asignamos como delegado a la clase ViewController, por lo tanto esta va a ser la encargada de cerrar la ventana desde donde enviamos el correo y manipular los resultados del envío, por lo tanto se espera que también implemente el método delegado mailComposeController:didFinishWithResult:error: de la clase MFMailComposeViewControllerDelegate. Nosotros si lo haremos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
    switch (result)
    {
        case MFMailComposeResultCancelled:
            self.estado.text = @"La operación ha sido cancelada";
            break;
        case MFMailComposeResultSaved:
            self.estado.text = @"El correo ha sido guardado en la carpeta borradores";
            break;
        case MFMailComposeResultSent:
            self.estado.text = @"Correo puesto en la cola de envío satisfactoriamente";
            break;
        case MFMailComposeResultFailed:
            self.estado.text = @"No se ha podido enviar o guardar el correo debido a un error";
            break;
        default:
            break;
    }

    // cerramos la ventana modal de envío de correo
    [controller dismissViewControllerAnimated:YES completion:nil];
}

Dependiendo de cual sea el evento, se devuelve un código de resultado diferente, esto nos permite personalizar la respuesta en cada caso.

Conclusión

Hoy hemos aprendido a enviar un mensaje de correo electrónico desde la misma aplicación. También hemos aprendido a mostrar la interfaz de envío con unos valores iniciales por defecto, así como a interceptar los mensajes de estado del envío del correo. Con respecto a esta clase, no hay mucho más que aprender, tan solo queda un par de cosas relacionadas con los mensajes de error en el método delegado, pero por lo demás, si haz comprendido bien este tutorial, ya puedes decir que dominas la clase MFMailComposeViewController :). No obstante para más detalle acerca de esta clase puedes pasarte por la documentación un momento, que siempre viene bien.

Espero que les haya gustado y servido. Cualquier duda, objeción o sugerencia la espero en los comentarios.

Comments