Como enviar e-mails do meu aplicativo Android?

Respostas:

978

A melhor (e mais fácil) maneira é usar um 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();
}

Caso contrário, você terá que escrever seu próprio cliente.

Jeremy Logan
fonte
6
No código acima, não há identificação de e-mail do remetente. Então, como a mensagem é enviada?
KIRAN KJ
38
KIRAN: Você precisará examinar como as Intents funcionam para entender isso. Basicamente, ele abre um aplicativo de email com o destinatário, o assunto e o corpo já preenchidos. Cabe ao aplicativo de e-mail fazer o envio.
11309 Jeremy Logan
8
O email não aparece no campo "PARA" iniciando a atividade. Alguém sabe?
Hamza Waqas 26/03
11
a grande contribuição deste comentário é: mensagem / rfc822
Guilherme Oliveira
22
adicione-os para garantir que o seletor exiba apenas aplicativos de e-mail: Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
Edris 7/15
194

Use .setType("message/rfc822")ou o seletor mostrará todos os (muitos) aplicativos que suportam a intenção de envio.

Jeff S
fonte
5
Bom, isso deve ter mais votos positivos. Você não notará os testes no emulador, mas quando enviar "texto / texto" em um dispositivo real, ele fornecerá uma lista de mais de 15 aplicativos! então "message / rfc822" é definitivamente recomendado (o padrão do email).
Blundell
7
@Blundell oi, mas não vi diferença depois de mudar paramessage/rfc822
draw
2
Você pode remover o bluetooth da lista? Isso também aparece com esse tipo. +1, porém, truque puro!
Ingh.am
4
Salvo nosso bacon. Não consigo imaginar explicar ao cliente que o usuário pode twittar solicitações de suporte em vez de enviá-las por email.
23412 Kevin Galligan
1
+1111111 Isso merece + 1s infinitos para que outros possam ver isso. Eu perdi essa parte e tive que lidar com esse problema por um tempo!
ChallengeAccepted
89

Eu uso isso há muito tempo e parece bom, nenhum aplicativo que não seja de e-mail aparecendo. Apenas outra maneira de enviar uma intenção de enviar email:

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'
fonte
1
Ação não suportada: atualmente, esta ação não é suportada
erdomester 25/03
4
lgor G-> plz mudança de setType "(plain / text") para setType ( "text / plain")
sachit
2
.setType ("message / rfc822") não texto / sem formatação
The Hungry Androider
1
esse código abrirá a intenção do e-mail? Como posso enviar e-mail sem mostrar intenção de usuário @yuku eu quero enviar senha para e-mail
Erum
2
Esta resposta é bastante influente . :)
Nick Volynkin
54

Eu estava usando algo como a resposta atualmente aceita para enviar emails com um arquivo de log de erros binários anexado. O GMail e o K-9 o enviam muito bem e também chegam bem no meu servidor de email. O único problema foi o meu cliente de email Thunderbird, que teve problemas com a abertura / salvamento do arquivo de log anexado. Na verdade, ele simplesmente não salvou o arquivo sem reclamar.

Examinei um desses códigos-fonte do correio e notei que o anexo do arquivo de log tinha (compreensivelmente) o tipo mime message/rfc822 . É claro que esse anexo não é um email anexado. Mas o Thunderbird não pode lidar com esse pequeno erro normalmente. Então isso foi meio chato.

Depois de um pouco de pesquisa e experimentação, vim com a seguinte solução:

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

Pode ser usado da seguinte maneira:

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 você pode ver, o método createEmailOnlyChooserIntent pode ser facilmente alimentado com a intenção correta e o tipo MIME correto.

Em seguida, ele percorre a lista de atividades disponíveis que respondem a uma mailtointenção do protocolo ACTION_SENDTO (que são apenas aplicativos de email) e constrói um seletor com base nessa lista de atividades e na intenção ACTION_SEND original com o tipo de mímica correto.

Outra vantagem é que o Skype não está mais listado (o que responde ao tipo mime rfc822).

tiguchi
fonte
1
Acabei de inserir o seu trecho de código e funciona bem. Antes de haver aplicativos listados como Google Drive, Skype etc. Mas não há como enviar um email para fora do aplicativo sem chamar outro aplicativo? Acabei de ler o artigo sobre o cliente de e-mail que @Rene postet acima, mas parece ser muito complicado para apenas enviar um e-mail simples
Alex Cio
Excelente resposta. Eu também tinha o Skype e o Google Drive ACTION_SEND, e isso explica tudo muito bem.
darrenp 4/09/13
1
A solução mais popular acima retorna o Skype e o Vkontakte também. Esta solução é melhor.
Denis Kutlubaev
o que é crashLogFile? onde ele inicializou? pease sepecify
Noufal
@Noufal Este é apenas um pouco da minha própria base de código. É uma Fileinstância que aponta para um arquivo de log de falha que meus aplicativos Android criam em segundo plano, caso haja uma exceção não detectada. Esse exemplo deve apenas ilustrar como adicionar um anexo de email. Você também pode anexar qualquer outro arquivo do armazenamento externo (uma imagem por exemplo). Você também pode remover essa linha crashLogFilepara obter um exemplo de trabalho.
tiguchi
37

Para deixar EMAIL APPS para resolver sua intenção, você precisa especificar ACTION_SENDTO como Ação e mailto como Dados.

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
fonte
23

Resolvi esse problema com linhas simples de código, conforme explica a documentação do Android.

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

O mais importante é a bandeira: é ACTION_SENDTO, e nãoACTION_SEND

A outra linha importante é

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

A propósito, se você enviar um vazio Extra, o if()final não funcionará e o aplicativo não iniciará o cliente de email.

De acordo com a documentação do Android. Se você deseja garantir que sua intenção seja tratada apenas por um aplicativo de email (e não por outros aplicativos de mensagens de texto ou sociais), use a ACTION_SENDTOação e inclua o " mailto:" esquema de dados. Por exemplo:

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
fonte
21

A estratégia de usar .setType("message/rfc822")ou ACTION_SENDparece também corresponder a aplicativos que não são clientes de email, como Android Beam e Bluetooth .

O uso de ACTION_SENDTOum mailto:URI parece funcionar perfeitamente e é recomendado na documentação do desenvolvedor . No entanto, se você fizer isso nos emuladores oficiais e não houver contas de email configuradas (ou não houver clientes de email), você receberá o seguinte erro:

Ação não suportada

Essa ação não é suportada no momento.

Como mostrado abaixo:

Ação não suportada: essa ação não é suportada no momento.

Acontece que os emuladores resolvem a intenção de uma atividade chamada com.android.fallback.Fallback, que exibe a mensagem acima.Aparentemente, isso ocorre por design.

Se você deseja que seu aplicativo contorne isso para que também funcione corretamente nos emuladores oficiais, verifique-o antes de tentar enviar o email:

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

Encontre mais informações na documentação do desenvolvedor .

Sam
fonte
13

O envio de email pode ser feito com o Intents, que não exigirá configuração. Mas isso exigirá interação do usuário e o layout será um pouco restrito.

Criar e enviar um email mais complexo sem a interação do usuário implica a criação de seu próprio cliente. A primeira coisa é que a API Sun Java para email não está disponível. Tive sucesso ao alavancar a biblioteca Apache Mime4j para criar email. Tudo baseado nos documentos da nilvec .

Rene
fonte
6

Aqui está o código de exemplo de trabalho que abre o aplicativo de correio no dispositivo Android e é preenchido automaticamente com o endereço Para e Assunto no e- mail de composição.

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
fonte
Obrigado. Comparando com uma solução do @Avi Parshan, você define um email setData()e o Avi define putExtra(). Ambas as variantes estão funcionando. Mas se remover setDatae usar apenas intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});, haveria um ActivityNotFoundException.
precisa saber é o seguinte
5

Eu uso o código abaixo em meus aplicativos. Isso mostra exatamente os aplicativos clientes de e-mail, como o 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
fonte
5

Isso mostrará apenas os clientes de e-mail (além do PayPal por algum motivo desconhecido)

 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
fonte
1
Ótima solução! Evita muitos aplicativos inadequados (usados ​​principalmente como "Compartilhar"). Não adicione intent.type = "message/rfc822"; intent.type = "text/html";aqui, pois isso levará à exceção.
precisa saber é o seguinte
3

Foi assim que eu fiz. Agradável e simples.

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 cães
fonte
3

Essa função primeiro direciona o gmail com intenção de enviar e-mail, se o gmail não for encontrado, promova o seletor de intenção. Eu usei essa função em muitos aplicativos comerciais e está funcionando bem. Espero que ajude você:

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
fonte
1
Muito obrigado. Salve minha vida
androCoder-BD
2

simples tente 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
fonte
3
Como isso é melhor do que as respostas que já existiam quando você postou isso? Parece uma cópia da resposta aceita, envolvida em uma atividade.
Sam
2

Outra solução pode 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);

Supondo que a maioria dos dispositivos Android já tenha o aplicativo GMail instalado.

silentsudo
fonte
@PedroVarela sempre podemos verificar a atividade não encontrada exceção.
silentsudo
1
Sim, nós podemos. Mas sua solução não é a correta. A documentação do Android indica claramente o que você deve fazer para mostrar apenas os aplicativos de correio no seletor de intenção. Você escreveu "Supondo que a maioria dos dispositivos Android já tenha o aplicativo Gmail instalado"; E se for um dispositivo raiz e o usuário excluir o cliente do Gmail? Suponha que você esteja criando seu próprio aplicativo de email ?, se um usuário enviar um email, seu aplicativo não estará nessa lista. O que acontece se o gmail alterar o nome do pacote? Você vai atualizar seu aplicativo?
Pedro Varela
2

Use isso para enviar email ...

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

use build gradle:

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

Usei esse código para enviar e-mail iniciando a seção de composição do aplicativo de e-mail padrão diretamente.

    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
fonte
1

Este método funciona para mim. Ele abre o aplicativo Gmail (se instalado) e define 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);
}
psicopata
fonte
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
fonte
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
fonte
1

Tente o seguinte:

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
}

O código acima abrirá o cliente de email favorito dos usuários pré-preenchido com o email pronto para enviar.

Fonte

Dan Bray
fonte