You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel:如何在会议开始前1小时精准发送提醒邮件?

实现会议开始前1小时精准发送提醒邮件的方案

针对你的需求,这里提供几种生产环境可用的实现方案,覆盖不同复杂度和场景:


方案一:定时任务轮询数据库(简单易实现)

适合中小规模场景,实现成本低,无需额外中间件。

步骤:

  1. 在meeting表新增reminder_sent字段(布尔型,默认false),标记是否已发送提醒,避免重复触发。
  2. 编写定时任务,每隔固定时间(比如1分钟)执行以下逻辑:
    • 查询所有start_time在「当前时间~当前时间+1小时」范围内,且reminder_sent = false的会议记录
    • 对每条记录调用邮件发送接口
    • 发送成功后更新reminder_sent为true

代码示例(Python + APScheduler):

import datetime
import mysql.connector
from apscheduler.schedulers.background import BackgroundScheduler
import smtplib
from email.mime.text import MIMEText

# 数据库连接配置
DB_CONFIG = {
    'user': 'your_user',
    'password': 'your_pwd',
    'host': 'localhost',
    'database': 'your_db'
}

# 邮件发送函数
def send_reminder_email(meeting_id, start_time, attendee_email):
    msg = MIMEText(f"提醒:会议ID {meeting_id} 将在 {start_time.strftime('%Y-%m-%d %H:%M')} 开始,请准时参加。")
    msg['Subject'] = '会议即将开始提醒'
    msg['From'] = 'reminder@yourcompany.com'
    msg['To'] = attendee_email

    with smtplib.SMTP('smtp.yourcompany.com', 587) as server:
        server.starttls()
        server.login('smtp_user', 'smtp_pwd')
        server.send_message(msg)

# 定时任务核心逻辑
def check_and_send_reminders():
    conn = mysql.connector.connect(**DB_CONFIG)
    cursor = conn.cursor(dictionary=True)
    
    now = datetime.datetime.now(datetime.timezone.utc)
    reminder_time = now + datetime.timedelta(hours=1)
    
    # 查询符合条件的会议(确保时区统一,这里假设start_time为UTC时间)
    query = """
        SELECT id, start_time, attendee_email 
        FROM meeting 
        WHERE start_time BETWEEN %s AND %s 
          AND reminder_sent = FALSE
    """
    cursor.execute(query, (now, reminder_time))
    meetings = cursor.fetchall()
    
    for meeting in meetings:
        try:
            send_reminder_email(meeting['id'], meeting['start_time'], meeting['attendee_email'])
            # 更新已发送标记
            update_query = "UPDATE meeting SET reminder_sent = TRUE WHERE id = %s"
            cursor.execute(update_query, (meeting['id'],))
            conn.commit()
        except Exception as e:
            print(f"发送会议 {meeting['id']} 提醒失败:{str(e)}")
            # 可记录日志,后续手动重试
    
    cursor.close()
    conn.close()

# 启动定时任务,每分钟执行一次
scheduler = BackgroundScheduler(timezone='UTC')
scheduler.add_job(check_and_send_reminders, 'interval', minutes=1)
scheduler.start()

# 保持进程运行
try:
    while True:
        datetime.datetime.now()
except (KeyboardInterrupt, SystemExit):
    scheduler.shutdown()

数据库层面实现(MySQL事件调度器):

-- 开启事件调度器
SET GLOBAL event_scheduler = ON;

-- 创建每分钟执行一次的事件
CREATE EVENT meeting_reminder_event
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
DO
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE meeting_id INT;
    DECLARE start_time DATETIME;
    DECLARE attendee_email VARCHAR(255);
    
    -- 游标查询待提醒会议
    DECLARE cur CURSOR FOR
        SELECT id, start_time, attendee_email 
        FROM meeting 
        WHERE start_time BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 1 HOUR)
          AND reminder_sent = FALSE;
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    OPEN cur;
    
    read_loop: LOOP
        FETCH cur INTO meeting_id, start_time, attendee_email;
        IF done THEN
            LEAVE read_loop;
        END IF;
        
        -- 调用自定义邮件发送存储过程(需提前实现)
        CALL send_meeting_reminder(meeting_id, start_time, attendee_email);
        
        -- 更新已发送标记
        UPDATE meeting SET reminder_sent = TRUE WHERE id = meeting_id;
    END LOOP;
    
    CLOSE cur;
END;

方案二:延迟消息队列(精准高效,适合大规模场景)

避免轮询的资源消耗,精准在指定时间触发提醒,同时支持会议修改/取消的场景。

步骤:

  1. 新增会议时,计算提醒时间:reminder_time = start_time - 1小时
  2. 计算当前时间到reminder_time的时间差,将会议信息(ID、参会人邮箱、会议时间等)发送到延迟队列,设置延迟时间为该差值
  3. 消费者服务监听队列,延迟时间到期后取出消息并发送提醒邮件
  4. 若会议被修改或取消,需从队列中删除对应的延迟消息(或标记为无效,消费时跳过)

代码示例(Redis延迟队列,Python):

import datetime
import redis
import json
import time
from threading import Thread

# Redis连接配置
r = redis.Redis(host='localhost', port=6379, db=0)

# 新增会议时添加延迟任务
def add_reminder_task(meeting_id, start_time, attendee_email):
    reminder_time = start_time - datetime.timedelta(hours=1)
    delay = (reminder_time - datetime.datetime.now(datetime.timezone.utc)).total_seconds()
    
    if delay > 0:
        task = json.dumps({
            'meeting_id': meeting_id,
            'attendee_email': attendee_email,
            'start_time': start_time.isoformat()
        })
        # 存入有序集合,score为提醒时间的时间戳
        r.zadd('meeting_reminders', {task: reminder_time.timestamp()})

# 消费者线程,持续处理到期任务
def consumer_thread():
    while True:
        now = datetime.datetime.now(datetime.timezone.utc).timestamp()
        # 取出所有到期任务
        tasks = r.zrangebyscore('meeting_reminders', 0, now, start=0, num=10)
        
        if tasks:
            for task in tasks:
                task_data = json.loads(task)
                try:
                    send_reminder_email(
                        task_data['meeting_id'],
                        datetime.datetime.fromisoformat(task_data['start_time']),
                        task_data['attendee_email']
                    )
                    # 发送成功后删除任务
                    r.zrem('meeting_reminders', task)
                except Exception as e:
                    print(f"处理任务失败:{str(e)}")
                    # 可将任务重新加入队列,或记录日志后续处理
        time.sleep(10)  # 每10秒检查一次

# 启动消费者线程
Thread(target=consumer_thread, daemon=True).start()

# 会议修改时更新提醒任务
def update_meeting_reminder(old_meeting_id, new_start_time, attendee_email):
    # 删除旧任务
    all_tasks = r.zrange('meeting_reminders', 0, -1)
    for task in all_tasks:
        task_data = json.loads(task)
        if task_data['meeting_id'] == old_meeting_id:
            r.zrem('meeting_reminders', task)
            break
    # 添加新任务
    add_reminder_task(old_meeting_id, new_start_time, attendee_email)

关键注意事项

  • 时区统一:确保数据库start_time、应用程序时间、调度任务时间使用同一时区(推荐UTC),避免时间偏差
  • 重复提醒避免:通过reminder_sent字段或队列任务删除机制,确保每个会议只发送一次提醒
  • 异常处理:邮件发送失败时添加重试机制(如间隔重试3次),或记录到失败队列后续人工处理
  • 会议变更处理:会议时间修改或取消时,及时更新/删除对应的提醒任务
  • 日志记录:记录所有提醒发送的成功/失败情况,便于排查问题

内容的提问来源于stack exchange,提问作者eksoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:13:09