【问题标题】:VSTO send email from custom Form button in OutlookVSTO 从 Outlook 中的自定义表单按钮发送电子邮件
【发布时间】:2020-12-09 19:53:25
【问题描述】:

我的目标是,用户想要发送一封新邮件,在填写(.TO.CC.Body 等)并点击发送按钮后会显示一个客户Form,其中发送选项是.一种选择是在用户创建电子邮件时发送电子邮件(正常的send 按钮功能)。 是否知道如何将ItemSend 函数分配给自定义表单中的按钮?

ThisAddIn.cs -> 打开自定义表单

public partial class ThisAddIn
{
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);

    }

Application_ItemSend

   private void Application_ItemSend(object Item, ref bool Cancel)
   {
        if (Item is Outlook.MailItem)
        {
            Form1 f = new Form1();
            f.Show();
        }

        Cancel = true;
    }

ChooseFormSend.cs -> 自定义发送按钮,

    public void btn_standard_Click(object sender, System.EventArgs e)
    {
         //mail.Send() -> send email which user whant to send        

    }

更新(所有要求一起,使这项工作)

ThisAddIn.cs

public partial class ThisAddIn
{
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);

    private bool ProcessEmail(Outlook.MailItem mailItem, MailSendType SendType)
    {
        switch (SendType)
        {
            case MailSendType.Normal:
                return false;

            case MailSendType.WithAdverts:
                //mailItem.BCC += "ad@server.xyz";
                mailItem.HTMLBody += @"<b>Some bold text at the end :)</b>";
                mailItem.HTMLBody += @"1233";
                return false; // send the mail

            case MailSendType.WithCoupon:
                mailItem.CC += "coupon@server.xyz";
                mailItem.HTMLBody += @"";
                return false; // send the mail

            // by default don't send the mail
            default:
                return true;
        }
    }

    private void Application_ItemSend(object Item, ref bool Cancel)
    {
        if (Item is MailItem) // ensures Item is a mail item
        {
            using (Form1 form_ChooseForm = new Form1())
            {
                DialogResult dr = form_ChooseForm.ShowDialog();
                if (dr == DialogResult.OK) // shows the form as a dialog
                {
                    Cancel = ProcessEmail((MailItem)Item, form_ChooseForm.SendType);
                    // MessageBox.Show("The OK button on the form was clicked.");                 
                }
                else
                {
                    // MessageBox.Show("Cancel process");
                    Cancel = true;
                }
            }   
        }
    }
}

ChooseFormSend.cs

using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using Microsoft.Office.Tools.Outlook;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Runtime.InteropServices;

namespace OutlookControll

{
    public enum MailSendType
    {
        NoSend,
        Normal,
        WithAdverts,
        WithCoupon
    }
    public partial class Form1 : Form
    {
    public Form1()
    {
        InitializeComponent();
    }

    public MailSendType SendType = MailSendType.NoSend;

    private void Btn_ShowSecondForm_Click(object sender, EventArgs e)
    {
        AddItemsForm f2 = new AddItemsForm();
        f2.ShowDialog();
        this.Hide();
    }

    private void Btn_cancel_Click(object sender, EventArgs e)
    {
        Button Btn_cancel_Click = new Button();
        Btn_cancel_Click.DialogResult = DialogResult.Cancel;
        this.Hide();
    }

    public void Btn_standard_Click(object sender, EventArgs e)
    {
        Button Btn_standard_Click = new Button();
        Btn_standard_Click.DialogResult = DialogResult.OK;
        Controls.Add(Btn_standard_Click);
        SendType = MailSendType.Normal;
        this.Hide();
    }

}

Btn_standard_Click.DialogResult = DialogResult.OK 可以设置在Properties -> Behavior -> DialogResult -> OK、Cancel、Abort 等

【问题讨论】:

  • 为什么不能使用 MailItem.Send?由于 Application_ItemSend 将再次触发,您可以设置自定义属性以跳过该电子邮件。或者您可以模态显示您的格式并将所有处理限制在 Application_ItemSend 处理程序中。
  • @dmitry streblechenko 所以添加到按钮 application_itemSend ?
  • 我不确定你的意思 - 按钮存在于表单中,而不是事件处理程序中。
  • 好的,那么表单按钮的部分代码 application_itemsend 应该放在哪里?
  • 在您的表单中。单击您的按钮将关闭您的表单并让 Application_ItemSend 继续执行。如果要取消提交,请将cancel参数设置为true。

标签: c# vsto outlook-addin outlook-2019


【解决方案1】:

我可以考虑 3 种可能的情况:

  1. 按发送 > 弹出表单 > 选择表单上的选项 > 修改电子邮件内容 > 发送电子邮件
  2. 按发送 > 弹出表单 > 选择表单上的选项 > 创建和发送新电子邮件(发送 1 封或多封新电子邮件)(丢弃旧电子邮件) > 发送电子邮件
  3. 按发送 > 弹出表单 > 选择表单上的选项 > 创建和发送新电子邮件(发送 1 封或多封新电子邮件)(发送旧电子邮件) > 发送电子邮件

请注意,一旦修改电子邮件内容可能意味着修改所有内容。更改发件人更改主题等。因此,如果您想创建一封新电子邮件并丢弃旧的选项 1 仍然可以完全操纵原始电子邮件。

允许用户选择相关选项的对话框。

注意:放置表单按钮时,请确保在属性检查器的“行为”下设置DialogResult 选项。这允许在单击自动关闭并从对话框返回的按钮之一后返回DialogResult:OK

public enum MailSendType
{
    NoSend,
    Normal,
    WithAdverts,
    WithCoupon
}

public partial class SendItemForm : Form
{
    public SendItemForm()
    {
        InitializeComponent();
    }

    public MailSendType SendType = MailSendType.NoSend;

    private void button1_Click(object sender, EventArgs e)
    {
        SendType = MailSendType.Normal;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        SendType = MailSendType.WithAdverts;
    }
}

方案一:只修改邮件内容

注意显示f.ShowDialog() 而不是f.Show() 这会阻止当前线程继续发送操作并等待用户选择表单上的按钮。对话框中的f.SendType 已设置并用于指示用户选择了哪个选项。使用ProcessEmail,我可以操纵电子邮件,return false 导致操纵电子邮件被发送,因为false 向下传播到父函数Cancel = false(不要取消发送)。

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        // create a global event listener for sending items
        Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
    }

    // this function is used to modify the mail object before sending it (More variables could be added to extend the functionality)
    private bool ProcessEmail(Outlook.MailItem mailItem, MailSendType sendType)
    {
        switch (sendType)
        {
            case MailSendType.Normal:
                return false; // send the mail as is don't mainpulate the mailItem variable

            case MailSendType.WithAdverts:
                mailItem.BCC += "ad@server.xyz";
                mailItem.HTMLBody += @"<b>Some bold text at the end :)</b>";
                mailItem.HTMLBody += @"</img src='https://server.xyz/ad1.png'>";
                return false; // send the mail

            case MailSendType.WithCoupon:
                mailItem.CC += "coupon@server.xyz";
                mailItem.HTMLBody += @"</img src='https://server.xyz/coupon1.png'>";
                return false; // send the mail

            // by default don't send the mail
            default:
                return true;
        }
    }

    private void Application_ItemSend(object Item, ref bool Cancel)
    {
        if (Item is Outlook.MailItem) // ensures Item is a mail item
        {
            using (SendItemForm f = new SendItemForm()) // creates the form
                if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK) // shows the form as a dialog
                    //if statement ensures the process will only proceed if an OK is returned 
                    //(The form has a cancel button or it could crash or anything else)
                    Cancel = ProcessEmail((Outlook.MailItem)Item, f.SendType); // process the email with the SendType
        }
    }

选项 2/3 发送新邮件

此方法重点介绍如何在 Outlook 中发送新电子邮件。注意:测试用MailItem.Send()发送邮件,它不会再次调用Application_ItemSend

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
    }

    private void SendNewEmail(string to, string greeting, MailSendType sendType)
    {
        Outlook.MailItem newMailItem = Application.CreateItem(Outlook.OlItemType.olMailItem);
        newMailItem.To = to;
        newMailItem.SendUsingAccount = Application.Session.Accounts[1]; // Optional can leave blank to send from default account (Array starts at 1)
        newMailItem.Subject = "New Mail";
        newMailItem.Body = $"{greeting} {newMailItem.To}\nExample Body from {sendType.ToString()}";

        // Part of Original answer but it's not relevant. However I will leave it in the event that it is of use to someone
        //((Outlook.ItemEvents_10_Event)newMailItem).Send += (ref bool Cancel) => { /*do nothing*/ };

        newMailItem.Send(); // send the mail
    }

    private void Application_ItemSend(object Item, ref bool Cancel)
    {
        if (Item is Outlook.MailItem) // ensures Item is a mail item
        {
            using (SendItemForm f = new SendItemForm()) // creates the form
                if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK) // shows the form as a dialog
                {
                    //if statement ensures the process will only proceed if an OK is returned 
                    //(The form has a cancel button or it could crash or anything else)

                    // send 3 mails
                    SendNewEmail("admin1@server.xyz", "Hi", f.SendType);
                    SendNewEmail("admin2@server.xyz", "Hello", MailSendType.Normal);
                    SendNewEmail("admin3@server.xyz", "Yo", f.SendType);

                    // either send or don't send the orginal one
                    // by default Cancel is set to false (So by default the message will send)

                    // send the 3 mails and send the original one typed up by the user
                    //Cancel = false;

                    // send the 3 mails and do not send the original one currently typed up by the user
                   // Cancel = true;
                }

        }
    }

在这 2 个示例和 f.ShowDialog() 设置之间,您应该能够找到您寻求的解决方案。您还可以通过修改原始电子邮件并发送额外的电子邮件来混合搭配。

【讨论】:

  • 我做错了什么,我遵循您的选项 1,只有当我单击取消按钮或使用表单右上角的十字按钮关闭表单时才会发送电子邮件。
  • void Application_ItemSend(object Item, ref bool Cancel)方法中可以设置Cancel变量。 Cancel = true; // Message will not send Cancel = false; // (Default) Message will send ShowDialog() 将返回 DialogResult.OKDialogResult.Cancel。从此您可以设置Cancel 请参阅Microsoft 示例并查看此StackOverflow post 以了解有关模态对话框如何工作的更多详细信息。
  • 更新了有关收集的所有信息的问题。让我们让它更复杂一点,如果我有第二个 Form 怎么办?发送其他类型的电子邮件? Application_ItemSend 控制第一个表单。第一个表单的一个按钮打开第二个表单,提示用户输入Imput,电子邮件发送给与第一个表单相同的收件人
  • 新更新的问题虽然有效,但与第一个问题并不完全相关。你最好问一个新问题。大问题可以分解为较小的目标问题。重点问题更适合 SO。搜索“multiform c# application”会出现很多结果。 This SO 链接显示了一些稍微复杂的处理多格式设置的方法。我还建议使用向导风格的方法(单击下一步并返回而不是打开新表单)
猜你喜欢
  • 1970-01-01
  • 2011-08-04
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多