【问题标题】:Send email from MySQL trigger when a table updated表更新时从 MySQL 触发器发送电子邮件
【发布时间】:2015-05-09 03:46:44
【问题描述】:

将表格视为table2,我想在此表格上添加trigger update

select Num into num from table1 where ID=new.id;
BEGIN
DECLARE done int default false;
DECLARE cur1 CURSOR FOR select EmailId from users where Num=num;
DECLARE continue handler for not found set done = true;
OPEN cur1;
my_loop: loop
    fetch cur1 into email_id;
    if done then
        leave my_loop;
    end if;
    //send mail to all email id.
end loop my_loop;
close cur1;
END;

有什么简单的方法可以在注释的地方写吗?向从表 users 检索到的所有电子邮件 ID 发送电子邮件。

我在 XAMPP(phpmyadmin) 中使用 MySQL。

【问题讨论】:

    标签: mysql sql email triggers sendmail


    【解决方案1】:

    您问,“有没有一种简单的方法可以...从触发器发送电子邮件”?

    答案是,在标准 MySQL 中没有。

    这通常通过创建某种 pending_message 表并编写客户端程序来定期轮询该表并发送消息来完成。

    或者,您可以考虑使用user-defined MySQL function。但大多数生产应用程序不太喜欢在其数据库中构建诸如电子邮件发送之类的网络功能,因为性能可能无法预测。

    【讨论】:

    • pending_message 表?请您解释一下这种编码方法。
    【解决方案2】:

    我反对这种解决方案。将发送电子邮件的负载放在数据库服务器中可能会非常糟糕。

    在我看来,您应该做的是创建一个表格,将您要发送的电子邮件排队,并有一个过程来检查是否有电子邮件要发送,如果是肯定的就发送它们。

    【讨论】:

    • 好主意,然后我可以在另一个表中插入所有这些电子邮件 ID 和相应的消息。那么,我该怎么办?你解释为have a process that checks if there are emails to be sent?我需要在哪里编写邮件发送代码?困惑。
    • 嗯,它可以通过多种方式完成。一些便宜的主机允许您运行每隔 X 分钟或小时安排的 php 脚本。您可以创建一个脚本来检查是否有要发送的电子邮件。如果您使用的是 VPS 或您自己的服务器。这取决于您使用的是基于 Unix 的操作系统还是 Windows。如果您在 Windows 上使用 GNU/Linux 或计划任务,请搜索 cronjobs。
    • 是的,我们可以使用 cronjobs 来实现这一点。但我还没有使用它。我正在使用 Windows 服务器。计划任务能很好地配合它吗?
    • 在 Windows 中,有一个等效的任务计划程序。
    • 如果对您有帮助,请选择正确答案。
    【解决方案3】:

    正如大家所说,让您的数据库来处理电子邮件是一个坏主意。让您的数据库写入外部文件是另一个坏主意,因为与数据库操作相比,IO 操作非常耗时。

    有几种方法可以处理您的问题,我喜欢一种:有一个表格来排列您的通知/电子邮件和一个客户端程序来发送电子邮件。

    在继续之前,您应该确保您有一个电子邮件帐户或可用于发送电子邮件的服务。它可以是 SMTP 或任何其他服务。

    如果你在 .NET 上,你可以复制这个,如果不是,你知道如何在你的平台上重写

    在您的数据库中创建一个表

    CREATE TABLE `tbl_system_mail_pickup` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `mFrom` varchar(128) NOT NULL DEFAULT 'noreplyccms@YourDomain.co.uk',
      `mTo` varchar(128) NOT NULL,
      `mCC` varchar(128) DEFAULT NULL,
      `mBCC` varchar(128) DEFAULT NULL,
      `mSubject` varchar(254) DEFAULT NULL,
      `mBody` longtext,
      `added_by` varchar(36) DEFAULT NULL,
      `updated_by` varchar(36) DEFAULT NULL,
      `added_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `updated_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      `email_sent` bit(1) DEFAULT b'0',
      `send_tried` int(11) DEFAULT '0',
      `send_result` text,
      PRIMARY KEY (`id`),
      UNIQUE KEY `id_UNIQUE` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    此表格将保存您的所有通知和电子邮件。您的表触发器或尝试发送电子邮件的事件将在上面的表中添加一条记录。然后,您的客户将按您指定的时间间隔接收电子邮件并发送。

    这是一个 .NET 上的示例控制台应用程序,只是为了让您了解客户端的外观。您可以根据需要对其进行修改。 (我使用实体框架更简单)

    1. 在 Visual Studio 中创建新的控制台项目。
    2. 在包管理器控制台中,安装以下包(安装包 EntityFramework,安装包 MySQL.Data.Entity)
    3. 添加对 System.Configuration 的引用
    4. 现在打开“App.Config”文件并将连接字符串添加到 MySQL 数据库。
    5. 在同一个 App.Config 文件中,添加您的 SMTP 电子邮件设置。 检查您的端口和 ssl 选项

        <system.net>
      <mailSettings>
        <smtp from="Noreplyccms@youractualEmailAccount.co.uk">
          <network host="smtp.office365.com(your host)" port="587" enableSsl="true" password="dingDong" userName="YourUsername@YourDomain" />
        </smtp>
      </mailSettings>
      

    6. 在项目树中创建名为 Models 的新文件夹。

    7. 添加新项目 -> ADO.NET 实体数据模型 -> 数据库中的 EF 设计器
    8. 选择您的连接字符串 -> 在 App.Config 中勾选保存连接设置 -> 为您的数据库命名。
    9. 下一步 -> 从您的数据库中仅选择上表并完成向导。

    现在您已经建立了与数据库和电子邮件配置的连接。是时候阅读并发送电子邮件了。

    这是一个完整的程序来理解这个概念。如果您有 Win 应用程序或 Web 应用程序配合此想法,您可以修改它。 此控制台应用程序将每分钟检查一次新的电子邮件记录并发送它们。您可以扩展上表和此脚本以添加附件。

    using System;
    using System.Linq;
    using System.Timers;
    using System.Data;
    using System.Net.Mail;
    using ccms_email_sender_console.Models;
    
    namespace ccms_email_sender_console
    {
        class Program
        {
    
           static Timer aTimer = new Timer();
            static void Main(string[] args)
            {
    
                aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);// add event to timer
                aTimer.Interval = 60000; // timer interval 
                aTimer.Enabled = true;
    
                Console.WriteLine("Press \'q\' to exit");
                while (Console.Read() != 'q');
    
            }
    
            private static void OnTimedEvent(object source, ElapsedEventArgs e)
            {
                var db_ccms_common = new DB_CCMS_COMMON(); // the database name you entered when creating ADO.NET Entity model
                Console.WriteLine(DateTime.Now+"> Checking server for emails:");
                aTimer.Stop(); /// stop the timer until we process current queue
    
                var query = from T1 in db_ccms_common.tbl_system_mail_pickup where T1.email_sent == false select T1; // select everything that hasn't been sent or marked as sent.
    
                try
                {
                    foreach (var mRow in query)
                    {
                        MailMessage mail = new MailMessage();
                        mail.To.Add(mRow.mTo.ToString());
                        if (mRow.mCC != null && !mRow.mCC.ToString().Equals(""))
                        {
                            mail.CC.Add(mRow.mCC.ToString());
    
                        }
                        if (mRow.mBCC != null && !mRow.mBCC.ToString().Equals(""))
                        {
                            mail.CC.Add(mRow.mBCC.ToString());
    
                        }
                        mail.From = new MailAddress(mRow.mFrom.ToString());
                        mail.Subject = mRow.mSubject.ToString();
                        mail.Body = mRow.mBody.ToString();
                        mail.IsBodyHtml = true;
    
                        SmtpClient smtp = new SmtpClient();
    
                        smtp.Send(mail);
    
                        mRow.email_sent = true;
                        Console.WriteLine(DateTime.Now + "> email sent to: " + mRow.mTo.ToString());
                    }
    
                    db_ccms_common.SaveChanges(); // mark all sent emails as sent. or you can also delete the record.
    
                    aTimer.Start(); // start the timer for next batch
                }
                catch (Exception ex)
                {
    
                    Console.WriteLine(DateTime.Now + "> Error:" + ex.Message.ToString());
                    // you can restart the timer here if you want
    
                }
    
            }
    
        }
    }
    

    测试:运行上面的代码并将一条记录插入到您的 tbl_system_mail_pickup 表中。大约 1 分钟后,您将收到一封发给您指定发件人的电子邮件。

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-13
      • 2013-11-01
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多