Як надсилати електронні листи з моєї програми Android?


Відповіді:


978

Найкращий (і найпростіший) спосіб - це використовувати 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();
}

Інакше вам доведеться написати власного клієнта.


6
У наведеному вище коді немає ідентифікатора електронної пошти відправника. Тоді як повідомлення надсилається?
KIRAN KJ

38
КІРАН: Вам потрібно буде вивчити, як працюють інтенти, щоб зрозуміти це. В основному це відкриє електронну заявку із одержувачем, темою та тілом, які вже заповнені. Надсилати додаток для електронної пошти потрібно.
Джеремі Логан

8
Електронний лист не відображається в полі "ДО", починаючи діяльність. хтось знає?
Hamza Waqas

11
великий внесок цього коментаря: message / rfc822
Guilherme Oliveira

22
додайте їх, щоб бути впевненим, що вибраний показ лише програм електронної пошти: Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
Едріс

194

Використовувати .setType("message/rfc822")або вибирач покаже вам усі (безліч) програм, які підтримують намір відправити.


5
Приємно, це повинно мати більше голосів тбх. Ви не помітите тестування на емуляторі, але коли ви перейдете надсилати "текст / звичайний" на реальний пристрій, він надасть вам список з 15+ додатків !! тому "message / rfc822" напевно рекомендується (стандарт електронної пошти).
Blundell

7
@Blundell привіт, але я не побачив різниці після зміниmessage/rfc822
розіграш

2
Чи можете ви видалити Bluetooth зі списку? Це також виявляється з цим типом. +1, однак, акуратний трюк!
ingh.am

4
Врятували наш бекон. Ви не уявляєте, як пояснити клієнтові, що користувач може твітувати запити підтримки, а не надсилати їм електронні листи.
Кевін Галліган

1
+1111111 Це заслуговує нескінченних оцінок +1, щоб інші могли бачити це. Я пропустив цю порцію і мав справу з цією проблемою деякий час!
ChallengeAccepted

89

Я використовую це з давніх-давен, і це здається гарним, не з’являються додатки, які не надходять по електронній пошті. Ще один спосіб надсилання наміру надіслати електронну пошту:

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

1
Непідтримувана дія: ця дія наразі не підтримується
erdomester

4
lgor G-> plz змінити з setType "(звичайний / текст") на setType ("текст / звичайний")
sachit

2
.setType ("message / rfc822") не текст / звичайний
The Hungry Androider

1
цей код відкриє наміри електронної пошти? як я можу надсилати електронну пошту, не виявляючи наміру користувачу @yuku, я хочу надіслати пароль на електронну пошту
Erum

2
Ця відповідь є досить впливовою . :)
Нік Волинкін

54

Я використовував щось уздовж рядків прийнятої на даний момент відповіді, щоб надсилати електронні листи із доданим файлом журналу помилок. 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.

Потім він проходить список доступних заходів, які відповідають на наміри mailtoпротоколу ACTION_SENDTO (які є лише програмами електронної пошти) та будує вибір, що базується на цьому списку дій та оригінальному намірі ACTION_SEND з правильним типом mime.

Ще одна перевага полягає в тому, що Skype більше не вказаний (що трапляється у відповідь на тип mime rfc822).


1
я щойно вставив вам фрагмент коду, і він працює добре. До того, як були перераховані додатки, такі як Google Drive, Skype тощо. Але чи не існує способу відправити пошту з програми без виклику іншої програми? я просто прочитав статтю про клієнта електронної пошти, який @Rene розмістив вище, але здається, що це занадто складно для простого надсилання простого електронного листа
Алекс Чіо

Відмінна відповідь. У мене також з’явились Skype та Google Drive, ACTION_SENDі це гарно розбирається.
darrenp

1
Найбільш популярне рішення вище повертає також Skype і Vkontakte. Це рішення краще.
Денис Кутлубаєв

що таке аваріяLogFile? де його ініціалізувати?
pease

@Noufal Це лише частина залишку моєї власної кодової бази. Це Fileекземпляр, який вказує на файл журналу аварій, який мої програми Android створюють у фоновому режимі, якщо виникла невдала виняток. Цей приклад повинен просто ілюструвати, як додати вкладення електронної пошти. Ви також можете приєднати будь-який інший файл із зовнішнього сховища (наприклад, зображення). Ви також можете видалити цей рядок crashLogFile, щоб отримати робочий приклад.
tiguchi

37

Щоб ПРОСТО ВІДБУТИ APPS- адреси електронної пошти, щоб вирішити свій намір, вам потрібно вказати ACTION_SENDTO як Action та mailto як Data.

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

}

23

Я вирішив цю проблему простими рядками коду, як пояснюється документація для 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);
    }
}

21

Стратегія використання .setType("message/rfc822")або, ACTION_SENDсхоже, також відповідає програмам, які не є клієнтами електронної пошти, наприклад Android Beam та Bluetooth .

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

Непідтримувана дія

Наразі ця дія не підтримується.

Як показано нижче:

Непідтримувана дія: ця дія наразі не підтримується.

Виявляється, емулятори вирішують наміри діяльності 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();
}

Додаткову інформацію можна знайти в документації для розробників .


13

Надсилання електронної пошти можна здійснити за допомогою Інтенсив, які не потребують конфігурації. Але тоді це вимагатиме взаємодії з користувачем, і макет буде трохи обмежений.

Створення та надсилання більш складного електронного листа без взаємодії з користувачем тягне за собою створення власного клієнта. Перше, що API Java Java для електронної пошти недоступний. У мене був успіх використання бібліотеки Apache Mime4j для створення електронної пошти. Все засновано на документах у nilvec .


6

Ось зразок робочого коду, який відкриває поштову програму на пристрої 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);
    }
}

Дякую. Порівнюючи з рішенням @Avi Parshan, ви встановлюєте електронний лист setData(), і Avi встановлює putExtra(). Обидва варіанти робочі. Але якщо вилучити setDataта використовувати лише intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});, було б a ActivityNotFoundException.
CoolMind

5

Я використовую наведений нижче код у своїх додатках. Це показує саме клієнтські програми, такі як 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)));

5

Це покаже вам лише клієнтів електронної пошти (а також PayPal з незрозумілої причини)

 public void composeEmail() {

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:"));
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});
    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();
    }
}

1
Приємне рішення! Це дозволяє уникнути багатьох непридатних додатків (в основному використовується як "Поділитися"). Не додайте intent.type = "message/rfc822"; intent.type = "text/html";сюди, оскільки це призведе до виключення.
CoolMind

3

Ось як я це зробив. Приємно і просто.

String emailUrl = "mailto:email@example.com?subject=Subject Text&body=Body Text";
        Intent request = new Intent(Intent.ACTION_VIEW);
        request.setData(Uri.parse(emailUrl));
        startActivity(request);

3

Ця функція спочатку спрямовує намір gmail для надсилання електронної пошти, якщо gmail не знайдена, то просувати вибір засобу вибору. Я використовував цю функцію в багатьох комерційних додатках, і вона працює чудово. Сподіваюся, це допоможе вам:

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

1
Дуже дякую. Врятуй моє життя
androCoder-BD

2

просто спробуйте це

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

        }
    });
}

3
Чим це краще, ніж відповіді, які вже існували, коли ви це публікували? Це просто схоже на копію прийнятої відповіді, завернуту в діяльність.
Сем

2

Інше рішення може бути

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[]{"someone@gmail.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);

Припустимо, що на більшості пристроїв для Android вже встановлено додаток GMail.


@PedroVarela ми завжди можемо перевірити, чи не виявлено виняток.
silentsudo

1
Так, ми можемо. Але ваше рішення не є правильним. У документації на Android чітко зазначено, що вам потрібно зробити, щоб у виборі намірів відображалися лише поштові програми. Ви написали "Припустимо, що на більшості пристроїв Android вже встановлено додаток Gmail"; Що робити, якщо це вкорінений пристрій і користувач видаляє клієнт Gmail ?. Припустимо, ви створюєте власну програму електронної пошти ?, якщо користувач збирається надіслати електронну пошту, ваша програма не буде в цьому списку. Що станеться, якщо gmail змінить назву пакета? Ви збираєтесь оновити додаток?
Педро Варела

2

Використовуйте це для надсилання електронної пошти ...

boolean success = EmailIntentBuilder.from(activity)
    .to("support@example.org")
    .cc("developer@example.org")
    .subject("Error report")
    .body(buildErrorReport())
    .start();

використовувати build gradle:

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

2

Я використовував цей код для надсилання пошти, безпосередньо запустивши розділ "Композиція пошти за замовчуванням".

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setType("message/rfc822"); 
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"test@gmail.com"});
    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();
    }

1

Цей метод працює для мене. Він відкриває додаток Gmail (якщо встановлено) та встановлює поштове повідомлення.

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

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

1
 Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
            "mailto","ebgsoldier@gmail.com", 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**

1

Спробуйте це:

String mailto = "mailto:bob@example.org" +
    "?cc=" + "alice@example.com" +
    "&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
}

Вищевказаний код відкриє улюбленому клієнту електронну пошту, попередньо заповненому електронною поштою, готовою до відправки.

Джерело

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.