当 table 更新时从 MySQL 触发发送电子邮件
Send email from MySQL trigger when a table updated
考虑一个table为table2
,我想在这个table上加一个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;
评论的地方有什么简单的写法吗?向从 table users
.
检索到的所有电子邮件 ID 发送电子邮件
我在 XAMPP(phpmyadmin) 中使用 MySQL。
你问,"is there a simple method to ... send a email"来自触发器?
答案是否,不符合标准MySQL。
这通常是通过创建某种 pending_message table 并编写客户端程序定期轮询 table 并发送消息来完成的。
或者,您可以考虑使用 user-defined MySQL function。但是大多数生产应用程序不太喜欢构建网络功能,比如将电子邮件发送到他们的数据库中,因为性能可能是不可预测的table。
我反对那个解决方案。将发送电子邮件的负载放在数据库服务器中可能会很糟糕。
在我看来,您应该做的是创建一个 table 来对您要发送的电子邮件进行排队,并有一个过程来检查是否有要发送的电子邮件,如果是则发送它们。
正如大家所说,让你的数据库来处理电子邮件是个坏主意。让你的数据库写入外部文件是另一个坏主意,因为与数据库操作相比,IO 操作非常耗时。
有几种方法可以解决您的问题,我喜欢一种方法:使用 table 来排队您的 notifications/emails 和使用客户端程序来发送电子邮件。
在你继续之前,你应该确保你有一个电子邮件帐户或服务可以用来发送电子邮件。它可以是 SMTP 或任何其他服务。
如果你在 .NET 上,你可以复制它,如果不是,你知道如何在你的平台上重写
在您的数据库中创建一个 table
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;
此 table 将保留您的所有通知和电子邮件。您的 Table 触发器或尝试发送电子邮件的事件将在 table 上方添加一条记录。然后,您的客户将按照您指定的时间间隔接收和发送电子邮件。
这是 .NET 上的示例控制台应用程序,只是为了让您了解客户端的外观。您可以根据需要进行修改。 (我使用 Entity-framework 因为它更容易和更简单)
- 在 Visual Studio 中创建新的控制台项目。
- 在包管理器控制台中,安装以下包(安装包 EntityFramework、安装包 MySQL.Data.Entity)
- 添加对 System.Configuration
的引用
- 现在打开 "App.Config" 文件并将连接字符串添加到 MySQL 数据库。
在同一个 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>
在项目树中创建名为 Models 的新文件夹。
- 添加新项目 -> ADO.NET 实体数据模型 -> 来自数据库的 EF 设计器
- Select 您的连接字符串 -> 勾选 App.Config 中的保存连接设置 -> 命名您的数据库。
- 下一步 -> Select 仅从您的数据库中获取上述 table 并完成向导。
现在您已经连接到您的数据库和电子邮件配置。是时候阅读并发送电子邮件了。
这是一个完整的程序来理解这个概念。如果您有 win 应用程序或 web 应用程序,您可以修改它。
此控制台应用程序将每分钟检查一次新电子邮件记录并发送它们。您可以扩展 table 和此脚本以添加附件。
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 table 中插入一条记录。大约 1 分钟后,您将收到一封发送给您指定的发件人的电子邮件。
希望这对某人有所帮助。
考虑一个table为table2
,我想在这个table上加一个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;
评论的地方有什么简单的写法吗?向从 table users
.
我在 XAMPP(phpmyadmin) 中使用 MySQL。
你问,"is there a simple method to ... send a email"来自触发器?
答案是否,不符合标准MySQL。
这通常是通过创建某种 pending_message table 并编写客户端程序定期轮询 table 并发送消息来完成的。
或者,您可以考虑使用 user-defined MySQL function。但是大多数生产应用程序不太喜欢构建网络功能,比如将电子邮件发送到他们的数据库中,因为性能可能是不可预测的table。
我反对那个解决方案。将发送电子邮件的负载放在数据库服务器中可能会很糟糕。
在我看来,您应该做的是创建一个 table 来对您要发送的电子邮件进行排队,并有一个过程来检查是否有要发送的电子邮件,如果是则发送它们。
正如大家所说,让你的数据库来处理电子邮件是个坏主意。让你的数据库写入外部文件是另一个坏主意,因为与数据库操作相比,IO 操作非常耗时。
有几种方法可以解决您的问题,我喜欢一种方法:使用 table 来排队您的 notifications/emails 和使用客户端程序来发送电子邮件。
在你继续之前,你应该确保你有一个电子邮件帐户或服务可以用来发送电子邮件。它可以是 SMTP 或任何其他服务。
如果你在 .NET 上,你可以复制它,如果不是,你知道如何在你的平台上重写
在您的数据库中创建一个 table
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;
此 table 将保留您的所有通知和电子邮件。您的 Table 触发器或尝试发送电子邮件的事件将在 table 上方添加一条记录。然后,您的客户将按照您指定的时间间隔接收和发送电子邮件。
这是 .NET 上的示例控制台应用程序,只是为了让您了解客户端的外观。您可以根据需要进行修改。 (我使用 Entity-framework 因为它更容易和更简单)
- 在 Visual Studio 中创建新的控制台项目。
- 在包管理器控制台中,安装以下包(安装包 EntityFramework、安装包 MySQL.Data.Entity)
- 添加对 System.Configuration 的引用
- 现在打开 "App.Config" 文件并将连接字符串添加到 MySQL 数据库。
在同一个 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>
在项目树中创建名为 Models 的新文件夹。
- 添加新项目 -> ADO.NET 实体数据模型 -> 来自数据库的 EF 设计器
- Select 您的连接字符串 -> 勾选 App.Config 中的保存连接设置 -> 命名您的数据库。
- 下一步 -> Select 仅从您的数据库中获取上述 table 并完成向导。
现在您已经连接到您的数据库和电子邮件配置。是时候阅读并发送电子邮件了。
这是一个完整的程序来理解这个概念。如果您有 win 应用程序或 web 应用程序,您可以修改它。 此控制台应用程序将每分钟检查一次新电子邮件记录并发送它们。您可以扩展 table 和此脚本以添加附件。
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 table 中插入一条记录。大约 1 分钟后,您将收到一封发送给您指定的发件人的电子邮件。
希望这对某人有所帮助。