Как я могу отправлять электронные письма из моего приложения Android? - PullRequest
499 голосов
/ 04 февраля 2010

Я пишу приложение для Android. Как мне с него отправить электронное письмо?

Ответы [ 19 ]

944 голосов
/ 04 февраля 2010

Лучший (и самый простой) способ - использовать Intent:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"recipient@example.com"});
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();
}

В противном случае вам придется написать собственный клиент.

191 голосов
/ 02 декабря 2010

Используйте .setType("message/rfc822"), или программа выбора покажет вам все (многие) приложения, которые поддерживают функцию отправки.

78 голосов
/ 27 февраля 2012

Я использую это с давних времен, и, кажется, это хорошо, никаких приложений без электронной почты не появляется. Просто еще один способ отправить письмо с намерением:

Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject of email");
intent.putExtra(Intent.EXTRA_TEXT, "Body of email");
intent.setData(Uri.parse("mailto:default@recipient.com")); // 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);
50 голосов
/ 09 октября 2012

Я использовал что-то вроде принятого в настоящее время ответа, чтобы отправлять электронные письма с приложенным двоичным файлом журнала ошибок.GMail и K-9 отправляют его очень хорошо, и он также приходит на мой почтовый сервер.Единственной проблемой был мой почтовый клиент по выбору Thunderbird, у которого были проблемы с открытием / сохранением прикрепленного файла журнала.На самом деле он просто не сохранил файл без жалоб.

Я взглянул на один из исходных кодов этих писем и заметил, что вложение файла журнала (понятно) имеет тип mime message/rfc822.Конечно, это вложение не является прикрепленным письмом.Но Thunderbird не может изящно справиться с этой крошечной ошибкой.Так что это было своего рода облом.

После небольшого количества исследований и экспериментов я нашел следующее решение:

    public Intent createEmailOnlyChooserIntent(Intent source,
        CharSequence chooserTitle) {
        Stack<Intent> intents = new Stack<Intent>();
        Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
                "info@domain.com", 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);
        }
    }

Его можно использовать следующим образом:

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

Как вы можете видеть, метод createEmailOnlyChooserIntent можно легко передать с правильным намерением и правильным типом mime.

Затем он проходит через список доступных действий, которые отвечают протоколу ACTION_SENDTO mailtointent (которые являются только приложениями электронной почты) и создает средство выбора на основе этого списка действий и исходного намерения ACTION_SEND с правильным типом MIME.

Другое преимущество заключается в том, что Skype больше не отображается в списке (что происходит в ответ натип mime rfc822).

34 голосов
/ 02 апреля 2014

Кому ПРОСТО ДАЙТЕ ПРИЛОЖЕНИЯ ПО ЭЛЕКТРОННОЙ ПОЧТЕ , чтобы разрешить свое намерение, вам нужно указать ACTION_SENDTO как Действие и mailto как Данные.

private void sendEmail(){

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:" + "recipient@example.com")); 
    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();
    }

}
19 голосов
/ 21 июля 2015

Я решил эту проблему с помощью простых строк кода, как объясняется в документации Android.

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

Наиболее важным является флаг: это ACTION_SENDTO, а не ACTION_SEND

Другая важная строка -

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

Кстати, если вы отправите пустой Extra, if() в конце не будет работать и приложение не запустит почтовый клиент.

Согласно документации Android. Если вы хотите, чтобы ваше намерение обрабатывалось только приложением электронной почты (а не другими приложениями для обмена текстовыми сообщениями или социальными приложениями), то используйте действие ACTION_SENDTO и добавьте "mailto: "схема данных. Например:

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);
    }
}
18 голосов
/ 25 июня 2015

Стратегия использования .setType("message/rfc822") или ACTION_SEND также подходит для приложений, не являющихся почтовыми клиентами, таких как Android Beam и Bluetooth .

Использование ACTION_SENDTO и mailto: URI, кажется, работает отлично, и рекомендуется в документации для разработчиков . Однако, если вы делаете это на официальных эмуляторах и не настроены учетные записи электронной почты (или нет почтовых клиентов), вы получите следующую ошибку:

Неподдерживаемое действие

Это действие в настоящее время не поддерживается.

Как показано ниже:

Unsupported action: That action is not currently supported.

Оказывается, что эмуляторы разрешают намерение для действия под названием com.android.fallback.Fallback, которое отображает вышеуказанное сообщение. Видимо, это так.

Если вы хотите, чтобы ваше приложение обошло это так, чтобы оно также корректно работало на официальных эмуляторах, вы можете проверить его, прежде чем пытаться отправить электронное письмо:

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 <johnsmith@yourdomain.com>" })
        .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();
}

Дополнительную информацию можно найти в документации разработчика .

12 голосов
/ 04 февраля 2010

Отправка электронной почты может быть выполнена с помощью Intents, которая не требует настройки.Но тогда это потребует взаимодействия с пользователем, а макет будет немного ограничен.

Создание и отправка более сложных электронных писем без взаимодействия с пользователем влечет за собой создание собственного клиента.Во-первых, Sun Java API для электронной почты недоступен.Я успешно использовал библиотеку Apache Mime4j для создания электронной почты.Все основано на документах на nilvec .

3 голосов
/ 20 сентября 2016

Я использую приведенный ниже код в своих приложениях.Это показывает именно почтовые клиентские приложения, такие как 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)));
3 голосов
/ 16 января 2018

Вот пример рабочего кода, который открывает почтовое приложение на устройстве Android и автоматически заполняется По адресу и Тема в составляющей почте. *

protected void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:feedback@gmail.com"));
    intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...