¿Cómo enviar correos electrónicos desde mi aplicación de Android?

Respuestas:

978

La mejor (y más fácil) forma es usar un Intent:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"[email protected]"});
i.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
i.putExtra(Intent.EXTRA_TEXT   , "body of email");
try {
    startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
    Toast.makeText(MyActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}

De lo contrario, tendrá que escribir su propio cliente.

Jeremy Logan
fuente
66
En el código anterior, no hay una identificación de correo electrónico del remitente. Entonces, ¿cómo se envía el mensaje?
KIRAN KJ
38
KIRAN: Tendrá que investigar cómo funcionan los Intents para comprender esto. Básicamente, abrirá una aplicación de correo electrónico con el destinatario, el asunto y el cuerpo ya completados. Depende de la aplicación de correo electrónico hacer el envío.
Jeremy Logan
8
El correo electrónico no aparece en el campo "PARA" al iniciar la actividad. ¿alguien sabe?
Hamza Waqas
11
La gran contribución de este comentario es: mensaje / rfc822
Guilherme Oliveira
22
agréguelos para asegurarse de que el selector muestra solo aplicaciones de correo electrónico: Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
Edris
194

Use .setType("message/rfc822")o el selector le mostrará todas las (muchas) aplicaciones que admiten la intención de envío.

Jeff S
fuente
55
Bien, esto debería tener más votos positivos. No notará las pruebas en el emulador, pero cuando vaya a enviar "texto / sin formato" en un dispositivo real, ¡le dará una lista de más de 15 aplicaciones! por lo que definitivamente se recomienda "mensaje / rfc822" (el estándar de correo electrónico).
Blundell
77
@Blundell hola, pero no vi ninguna diferencia después de cambiar amessage/rfc822
sorteo
2
¿Se puede eliminar bluetooth de la lista? Esto también aparece con este tipo. ¡+1 sin embargo, buen truco!
ingh.am
44
Salvó nuestro tocino. No puedo imaginar explicarle al cliente que el usuario podría tuitear solicitudes de soporte en lugar de enviarlas por correo electrónico.
Kevin Galligan el
1
+1111111 Esto merece infinitos +1 para que otros puedan ver esto. ¡Me perdí esta porción y tuve que lidiar con este problema por un tiempo!
Desafío
89

He estado usando esto desde hace mucho tiempo y parece bueno, no aparecen aplicaciones que no sean de correo electrónico. Solo otra forma de enviar un intento de envío de correo electrónico:

Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject of email");
intent.putExtra(Intent.EXTRA_TEXT, "Body of email");
intent.setData(Uri.parse("mailto:[email protected]")); // or just "mailto:" for blank
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this will make such that when user returns to your app, your app is displayed, instead of the email app.
startActivity(intent);
Randy Sugianto 'Yuku'
fuente
1
Acción no admitida: esta acción no es compatible actualmente
erdomester
44
lgor G-> por favor cambie de setType "(sin formato / texto") a setType ("texto / sin formato")
sachit
2
.setType ("message / rfc822") no text / plain
The Hungry Androider
1
Este código abrirá la intención del correo electrónico? ¿Cómo puedo enviar un correo electrónico sin mostrar intención al usuario @yuku? Quiero enviar una contraseña al correo electrónico
Erum
2
Esta respuesta es bastante influyente . :)
Nick Volynkin
54

Estaba usando algo similar a la respuesta actualmente aceptada para enviar correos electrónicos con un archivo de registro de error binario adjunto. GMail y K-9 lo envían bien y también llega bien a mi servidor de correo. El único problema era mi cliente de correo de elección Thunderbird que tenía problemas para abrir / guardar el archivo de registro adjunto. De hecho, simplemente no guardó el archivo en absoluto sin quejarse.

Eché un vistazo a uno de los códigos fuente de estos correos y noté que el archivo adjunto de registro tenía (comprensiblemente) el tipo mime message/rfc822. Por supuesto, ese archivo adjunto no es un correo electrónico adjunto. Pero Thunderbird no puede hacer frente a ese pequeño error con gracia. Así que fue un fastidio.

Después de un poco de investigación y experimentación, se me ocurrió la siguiente solución:

public Intent createEmailOnlyChooserIntent(Intent source,
    CharSequence chooserTitle) {
    Stack<Intent> intents = new Stack<Intent>();
    Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
            "[email protected]", null));
    List<ResolveInfo> activities = getPackageManager()
            .queryIntentActivities(i, 0);

    for(ResolveInfo ri : activities) {
        Intent target = new Intent(source);
        target.setPackage(ri.activityInfo.packageName);
        intents.add(target);
    }

    if(!intents.isEmpty()) {
        Intent chooserIntent = Intent.createChooser(intents.remove(0),
                chooserTitle);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
                intents.toArray(new Parcelable[intents.size()]));

        return chooserIntent;
    } else {
        return Intent.createChooser(source, chooserTitle);
    }
}

Se puede usar de la siguiente manera:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("*/*");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(crashLogFile));
i.putExtra(Intent.EXTRA_EMAIL, new String[] {
    ANDROID_SUPPORT_EMAIL
});
i.putExtra(Intent.EXTRA_SUBJECT, "Crash report");
i.putExtra(Intent.EXTRA_TEXT, "Some crash report details");

startActivity(createEmailOnlyChooserIntent(i, "Send via email"));

Como puede ver, el método createEmailOnlyChooserIntent se puede alimentar fácilmente con la intención correcta y el tipo mime correcto.

Luego revisa la lista de actividades disponibles que responden a una mailtointención de protocolo ACTION_SENDTO (que son solo aplicaciones de correo electrónico) y construye un selector basado en esa lista de actividades y la intención ACTION_SEND original con el tipo mime correcto.

Otra ventaja es que Skype ya no aparece en la lista (lo que sucede para responder al tipo mime rfc822).

tiguchi
fuente
1
Acabo de insertar su fragmento de código y funciona bien. Antes había habido una lista de aplicaciones como Google Drive, Skype, etc. ¿Pero no hay una manera de enviar un correo desde la aplicación sin llamar a otra aplicación? Acabo de leer el artículo sobre el cliente de correo electrónico que @Rene publicó anteriormente, pero parece ser demasiado complicado para enviar un correo electrónico simple
Alex Cio
Excelente respuesta También se me ocurrió Skype y Google Drive ACTION_SENDy esto lo soluciona maravillosamente.
darrenp
1
La solución más popular anterior también devuelve Skype y Vkontakte. Esta solución es mejor.
Denis Kutlubaev
¿Qué es crashLogFile? ¿Dónde se inicializó? pease sepecify
Noufal
@Noufal Esto es solo un resto de mi propia base de código. Es una Fileinstancia que apunta a un archivo de registro de bloqueo que mis aplicaciones de Android crean en segundo plano en caso de que haya una excepción no detectada. Ese ejemplo debería ilustrar cómo agregar un archivo adjunto de correo electrónico. También puede adjuntar cualquier otro archivo del almacenamiento externo (una imagen, por ejemplo). También puede eliminar esa línea con crashLogFilepara obtener un ejemplo de trabajo.
tiguchi
37

Para SOLO DEJAR APLICACIONES DE CORREO ELECTRÓNICO para resolver su intención, debe especificar ACTION_SENDTO como Acción y mailto como Datos.

private void sendEmail(){

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:" + "[email protected]")); 
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "My email's subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "My email's body");

    try {
        startActivity(Intent.createChooser(emailIntent, "Send email using..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(Activity.this, "No email clients installed.", Toast.LENGTH_SHORT).show();
    }

}
wildzic
fuente
23

Resolví este problema con líneas de código simples como explica la documentación de Android.

( https://developer.android.com/guide/components/intents-common.html#Email )

Lo más importante es la bandera: es ACTION_SENDTO, y noACTION_SEND

La otra línea importante es

intent.setData(Uri.parse("mailto:")); ***// only email apps should handle this***

Por cierto, si envía un mensaje vacío Extra, if()al final no funcionará y la aplicación no iniciará el cliente de correo electrónico.

De acuerdo con la documentación de Android. Si desea asegurarse de que su intención sea manejada solo por una aplicación de correo electrónico (y no por otras aplicaciones de mensajes de texto o sociales), utilice la ACTION_SENDTOacción e incluya el " mailto:" esquema de datos. Por ejemplo:

public void composeEmail(String[] addresses, String subject) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:")); // only email apps should handle this
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}
Pedro Varela
fuente
21

La estrategia de usar .setType("message/rfc822")o ACTION_SENDparece coincidir también con aplicaciones que no son clientes de correo electrónico, como Android Beam y Bluetooth .

Usar ACTION_SENDTOy un mailto:URI parece funcionar perfectamente, y se recomienda en la documentación del desarrollador . Sin embargo, si hace esto en los emuladores oficiales y no hay ninguna cuenta de correo electrónico configurada (o no hay clientes de correo), obtendrá el siguiente error:

Acción no admitida

Esa acción no es compatible actualmente.

Como se muestra abajo:

Acción no admitida: esa acción no se admite actualmente.

Resulta que los emuladores resuelven la intención de una actividad llamada com.android.fallback.Fallback, que muestra el mensaje anterior. Aparentemente esto es por diseño.

Si desea que su aplicación evite esto para que también funcione correctamente en los emuladores oficiales, puede verificarlo antes de intentar enviar el correo electrónico:

private void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO)
        .setData(new Uri.Builder().scheme("mailto").build())
        .putExtra(Intent.EXTRA_EMAIL, new String[]{ "John Smith <[email protected]>" })
        .putExtra(Intent.EXTRA_SUBJECT, "Email subject")
        .putExtra(Intent.EXTRA_TEXT, "Email body")
    ;

    ComponentName emailApp = intent.resolveActivity(getPackageManager());
    ComponentName unsupportedAction = ComponentName.unflattenFromString("com.android.fallback/.Fallback");
    if (emailApp != null && !emailApp.equals(unsupportedAction))
        try {
            // Needed to customise the chooser dialog title since it might default to "Share with"
            // Note that the chooser will still be skipped if only one app is matched
            Intent chooser = Intent.createChooser(intent, "Send email with");
            startActivity(chooser);
            return;
        }
        catch (ActivityNotFoundException ignored) {
        }

    Toast
        .makeText(this, "Couldn't find an email app and account", Toast.LENGTH_LONG)
        .show();
}

Encuentre más información en la documentación del desarrollador .

Sam
fuente
13

El envío de correo electrónico se puede hacer con Intents que no requerirán configuración. Pero luego requerirá la interacción del usuario y el diseño será un poco restringido.

Construir y enviar un correo electrónico más complejo sin interacción del usuario implica construir su propio cliente. Lo primero es que la API Sun Java para correo electrónico no está disponible. He tenido éxito aprovechando la biblioteca Apache Mime4j para crear correos electrónicos. Todo basado en los documentos de nilvec .

René
fuente
6

Aquí está el código de trabajo de muestra que abre la aplicación de correo en el dispositivo Android y se llena automáticamente con la dirección Para y el Asunto en el correo de redacción.

protected void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:[email protected]"));
    intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}
Sridhar Nalam
fuente
Gracias. En comparación con una solución de @Avi Parshan, configura un correo electrónico setData()y Avi lo establece putExtra(). Ambas variantes de trabajo. Pero si solo se quita setDatay usa intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});, habría un ActivityNotFoundException.
CoolMind
5

Yo uso el siguiente código en mis aplicaciones. Esto muestra exactamente las aplicaciones cliente de correo electrónico, como Gmail.

    Intent contactIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", getString(R.string.email_to), null));
    contactIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject));
    startActivity(Intent.createChooser(contactIntent, getString(R.string.email_chooser)));
lomza
fuente
5

Esto le mostrará solo los clientes de correo electrónico (así como PayPal por alguna razón desconocida)

 public void composeEmail() {

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:"));
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
    intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    intent.putExtra(Intent.EXTRA_TEXT, "Body");
    try {
        startActivity(Intent.createChooser(intent, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
}
Avi Parshan
fuente
1
Buena solución! Evita muchas aplicaciones inadecuadas (utilizadas principalmente como "Compartir"). No agregue intent.type = "message/rfc822"; intent.type = "text/html";aquí ya que conducirá a la excepción.
CoolMind
3

Así es como lo hice. Agradable y simple

String emailUrl = "mailto:[email protected]?subject=Subject Text&body=Body Text";
        Intent request = new Intent(Intent.ACTION_VIEW);
        request.setData(Uri.parse(emailUrl));
        startActivity(request);
Amante de los perros
fuente
3

Esta función es la primera intención directa de gmail para enviar correos electrónicos; si no se encuentra gmail, promueva el selector de intenciones. Utilicé esta función en muchas aplicaciones comerciales y funciona bien. Espero que te ayude:

public static void sentEmail(Context mContext, String[] addresses, String subject, String body) {

    try {
        Intent sendIntentGmail = new Intent(Intent.ACTION_VIEW);
        sendIntentGmail.setType("plain/text");
        sendIntentGmail.setData(Uri.parse(TextUtils.join(",", addresses)));
        sendIntentGmail.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
        sendIntentGmail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentGmail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentGmail.putExtra(Intent.EXTRA_TEXT, body);
        mContext.startActivity(sendIntentGmail);
    } catch (Exception e) {
        //When Gmail App is not installed or disable
        Intent sendIntentIfGmailFail = new Intent(Intent.ACTION_SEND);
        sendIntentIfGmailFail.setType("*/*");
        sendIntentIfGmailFail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_TEXT, body);
        if (sendIntentIfGmailFail.resolveActivity(mContext.getPackageManager()) != null) {
            mContext.startActivity(sendIntentIfGmailFail);
        }
    }
}
Shohan Ahmed Sijan
fuente
1
Muchas gracias. Salva mi vida
androCoder-BD
2

simple prueba este

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    buttonSend = (Button) findViewById(R.id.buttonSend);
    textTo = (EditText) findViewById(R.id.editTextTo);
    textSubject = (EditText) findViewById(R.id.editTextSubject);
    textMessage = (EditText) findViewById(R.id.editTextMessage);

    buttonSend.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            String to = textTo.getText().toString();
            String subject = textSubject.getText().toString();
            String message = textMessage.getText().toString();

            Intent email = new Intent(Intent.ACTION_SEND);
            email.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
            // email.putExtra(Intent.EXTRA_CC, new String[]{ to});
            // email.putExtra(Intent.EXTRA_BCC, new String[]{to});
            email.putExtra(Intent.EXTRA_SUBJECT, subject);
            email.putExtra(Intent.EXTRA_TEXT, message);

            // need this to prompts email client only
            email.setType("message/rfc822");

            startActivity(Intent.createChooser(email, "Choose an Email client :"));

        }
    });
}
NagarjunaReddy
fuente
3
¿Cómo es esto mejor que las respuestas que ya existían cuando publicaste esto? Simplemente parece una copia de la respuesta aceptada envuelta en una actividad.
Sam
2

Otra solución puede ser

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("plain/text");
emailIntent.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);

Asumiendo que la mayoría del dispositivo Android tiene la aplicación GMail ya instalada.

silentsudo
fuente
@PedroVarela siempre podemos verificar la actividad no encontrada excepción.
silentsudo
1
Si podemos. Pero su solución no es la correcta. La documentación de Android establece claramente lo que debe hacer para mostrar solo las aplicaciones de correo en el selector de intención. Usted escribió "Suponiendo que la mayoría del dispositivo Android ya tenga instalada la aplicación Gmail"; ¿Qué pasa si es un dispositivo rooteado y el usuario elimina el cliente de Gmail? ¿Supongamos que está creando su propia aplicación de correo electrónico ?, si un usuario va a enviar un correo electrónico, su aplicación no estará en esa lista. ¿Qué sucede si gmail cambia el nombre del paquete? ¿Vas a actualizar tu aplicación?
Pedro Varela
2

Use esto para enviar correos electrónicos ...

boolean success = EmailIntentBuilder.from(activity)
    .to("[email protected]")
    .cc("[email protected]")
    .subject("Error report")
    .body(buildErrorReport())
    .start();

usar build gradle:

compile 'de.cketti.mailto:email-intent-builder:1.0.0'
Manish
fuente
2

Utilicé este código para enviar correo iniciando directamente la sección de redacción de la aplicación de correo predeterminada.

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setType("message/rfc822"); 
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"[email protected]"});
    i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    i.putExtra(Intent.EXTRA_TEXT   , "body of email");
    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
Faris Muhammed
fuente
1

Este método me funciona. Abre la aplicación Gmail (si está instalada) y configura mailto.

public void openGmail(Activity activity) {
    Intent emailIntent = new Intent(Intent.ACTION_VIEW);
    emailIntent.setType("text/plain");
    emailIntent.setType("message/rfc822");
    emailIntent.setData(Uri.parse("mailto:"+activity.getString(R.string.mail_to)));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name) + " - info ");
    final PackageManager pm = activity.getPackageManager();
    final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
    ResolveInfo best = null;
    for (final ResolveInfo info : matches)
        if (info.activityInfo.packageName.endsWith(".gm") || info.activityInfo.name.toLowerCase().contains("gmail"))
            best = info;
    if (best != null)
        emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
    activity.startActivity(emailIntent);
}
psicópata
fuente
1
/**
 * Will start the chosen Email app
 *
 * @param context    current component context.
 * @param emails     Emails you would like to send to.
 * @param subject    The subject that will be used in the Email app.
 * @param forceGmail True - if you want to open Gmail app, False otherwise. If the Gmail
 *                   app is not installed on this device a chooser will be shown.
 */
public static void sendEmail(Context context, String[] emails, String subject, boolean forceGmail) {

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL, emails);
    i.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (forceGmail && isPackageInstalled(context, "com.google.android.gm")) {
        i.setPackage("com.google.android.gm");
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    } else {
        try {
            context.startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (ActivityNotFoundException e) {
            Toast.makeText(context, "No email app is installed on your device...", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * Check if the given app is installed on this devuice.
 *
 * @param context     current component context.
 * @param packageName The package name you would like to check.
 * @return True if this package exist, otherwise False.
 */
public static boolean isPackageInstalled(@NonNull Context context, @NonNull String packageName) {
    PackageManager pm = context.getPackageManager();
    if (pm != null) {
        try {
            pm.getPackageInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}
Gal rom
fuente
1
 Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
            "mailto","[email protected]", null));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Forgot Password");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Write your Pubg user name or Phone Number");
    startActivity(Intent.createChooser(emailIntent, "Send email..."));**strong text**
Tousif Akram
fuente
1

Prueba esto:

String mailto = "mailto:[email protected]" +
    "?cc=" + "[email protected]" +
    "&subject=" + Uri.encode(subject) +
    "&body=" + Uri.encode(bodyText);

Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));

try {
    startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
    //TODO: Handle case where no email app is available
}

El código anterior abrirá el cliente de correo electrónico favorito de los usuarios previamente completado con el correo electrónico listo para enviar.

Fuente

Dan Bray
fuente