关于 email-construction
面向施工项目团队的邮件生成技能,提供常见沟通场景的结构化模板,涵盖 RFI 回复、报审资料、会议、变更单和延误通知。
主要功能
- 01生成 RFI 回复邮件
- 02创建报审资料和会议邮件
- 03起草变更单及延误通知
- 04支持 SMTP 邮件发送
适用场景
- 01根据项目详情回复 RFI
- 02发送报审资料供审核
- 03通知团队会议或变更事项
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ datadrivenconstruction/ ddc_skills_for_ai_agents_in_construction --skill email-construction安装后在 Claude Code 中输入/email-construction确认已加载。
附带文件claw.jsoninstructions.md
详细介绍
建筑施工邮件生成
概述
生成格式规范、内容贴合上下文且妥善处理附件的专业建筑施工邮件。提供适用于常见建筑施工沟通工作流的模板。
建筑施工应用场景
1. RFI 回复邮件
生成专业的 RFI 回复邮件。
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, List
@dataclass
class RFIResponse:
rfi_number: str
project_name: str
subject: str
question: str
response: str
responder_name: str
responder_title: str
attachments: List[str] = None
cc_list: List[str] = None
def generate_rfi_response_email(rfi: RFIResponse) -> dict:
"""Generate RFI response email."""
subject = f"RE: RFI #{rfi.rfi_number} - {rfi.subject}"
body = f"""Dear Project Team,
Please find below our response to RFI #{rfi.rfi_number}.
**Project:** {rfi.project_name}
**RFI Number:** {rfi.rfi_number}
**Subject:** {rfi.subject}
**Date:** {datetime.now().strftime('%B %d, %Y')}
---
**QUESTION:**
{rfi.question}
---
**RESPONSE:**
{rfi.response}
---
Please proceed accordingly. If you have any questions regarding this response, please contact us.
{"**Attachments:**" + chr(10) + chr(10).join(f"- {a}" for a in rfi.attachments) if rfi.attachments else ""}
Best regards,
{rfi.responder_name}
{rfi.responder_title}
"""
return {
'subject': subject,
'body': body,
'cc': rfi.cc_list or [],
'attachments': rfi.attachments or []
}
2. 送审文件传递邮件
生成送审文件传递邮件。
@dataclass
class SubmittalTransmittal:
submittal_number: str
project_name: str
spec_section: str
description: str
items: List[dict]
action_required: str
due_date: str
sender_name: str
sender_company: str
def generate_submittal_email(submittal: SubmittalTransmittal) -> dict:
"""Generate submittal transmittal email."""
subject = f"Submittal {submittal.submittal_number} - {submittal.spec_section} - {submittal.description}"
items_list = "\n".join(
f" {i+1}. {item['description']} ({item.get('copies', 1)} copies)"
for i, item in enumerate(submittal.items)
)
body = f"""Dear Design Team,
Please find attached Submittal {submittal.submittal_number} for your review.
**Project:** {submittal.project_name}
**Submittal No:** {submittal.submittal_number}
**Spec Section:** {submittal.spec_section}
**Description:** {submittal.description}
**Items Transmitted:**
{items_list}
**Action Required:** {submittal.action_required}
**Response Requested By:** {submittal.due_date}
Please review and return with your comments at your earliest convenience.
If you have any questions, please don't hesitate to contact us.
Best regards,
{submittal.sender_name}
{submittal.sender_company}
"""
return {
'subject': subject,
'body': body,
'priority': 'normal'
}
3. 会议通知邮件
生成会议邀请邮件。
@dataclass
class MeetingNotice:
meeting_type: str # 'OAC', 'Subcontractor', 'Safety', 'Coordination'
project_name: str
date: str
time: str
location: str
virtual_link: Optional[str]
agenda_items: List[str]
attendees: List[str]
organizer_name: str
def generate_meeting_notice(meeting: MeetingNotice) -> dict:
"""Generate meeting notice email."""
subject = f"{meeting.meeting_type} Meeting - {meeting.project_name} - {meeting.date}"
agenda = "\n".join(f" {i+1}. {item}" for i, item in enumerate(meeting.agenda_items))
location_info = meeting.location
if meeting.virtual_link:
location_info += f"\n Virtual Option: {meeting.virtual_link}"
body = f"""Dear Team,
You are invited to the {meeting.meeting_type} Meeting for {meeting.project_name}.
**Meeting Details:**
- **Date:** {meeting.date}
- **Time:** {meeting.time}
- **Location:** {location_info}
**Agenda:**
{agenda}
**Attendees:**
{', '.join(meeting.attendees)}
Please confirm your attendance by replying to this email.
If you cannot attend, please send a delegate and notify the organizer.
Regards,
{meeting.organizer_name}
Project Manager
"""
return {
'subject': subject,
'body': body,
'to': meeting.attendees,
'calendar_invite': {
'start': f"{meeting.date} {meeting.time}",
'duration': 60,
'location': meeting.location
}
}
4. 变更单通知
生成变更单通知邮件。
@dataclass
class ChangeOrderNotification:
co_number: str
project_name: str
description: str
amount: float
schedule_impact: str
reason: str
status: str # 'Pending', 'Approved', 'Rejected'
sender_name: str
sender_title: str
def generate_change_order_email(co: ChangeOrderNotification) -> dict:
"""Generate change order notification email."""
subject = f"Change Order #{co.co_number} - {co.status} - {co.project_name}"
amount_str = f"${co.amount:,.2f}"
if co.amount < 0:
amount_str = f"(${abs(co.amount):,.2f}) Credit"
body = f"""Dear Project Team,
This email is to notify you of Change Order #{co.co_number} for {co.project_name}.
**Change Order Details:**
- **CO Number:** {co.co_number}
- **Status:** {co.status}
- **Description:** {co.description}
**Financial Impact:**
- **Amount:** {amount_str}
**Schedule Impact:**
- {co.schedule_impact}
**Reason for Change:**
{co.reason}
{"Please review the attached documentation and provide your approval." if co.status == 'Pending' else ""}
{"This change order has been approved. Please proceed accordingly." if co.status == 'Approved' else ""}
If you have any questions, please contact the project team.
Best regards,
{co.sender_name}
{co.sender_title}
"""
return {
'subject': subject,
'body': body,
'priority': 'high' if co.status == 'Pending' else 'normal',
'flag': co.status == 'Pending'
}
5. 每日报告邮件
生成每日报告分发邮件。
@dataclass
class DailyReportEmail:
project_name: str
report_date: str
report_number: int
weather: str
workforce_total: int
work_summary: List[str]
issues: List[str]
sender_name: str
def generate_daily_report_email(report: DailyReportEmail) -> dict:
"""Generate daily report distribution email."""
subject = f"Daily Report #{report.report_number} - {report.project_name} - {report.report_date}"
work_items = "\n".join(f"• {item}" for item in report.work_summary)
issues_text = "\n".join(f"• {issue}" for issue in report.issues) if report.issues else "None"
body = f"""Daily Construction Report
**Project:** {report.project_name}
**Date:** {report.report_date}
**Report #:** {report.report_number}
---
**Weather:** {report.weather}
**Total Workforce:** {report.workforce_total} workers on-site
---
**Work Completed:**
{work_items}
---
**Issues/Delays:**
{issues_text}
---
Full report attached. Please contact the site office with any questions.
{report.sender_name}
Site Superintendent
"""
return {
'subject': subject,
'body': body,
'attachments': [f'Daily_Report_{report.report_number}.pdf']
}
6. 延误通知邮件
生成正式的延误通知。
@dataclass
class DelayNotice:
project_name: str
contract_number: str
delay_type: str # 'Excusable', 'Non-Excusable', 'Compensable'
cause: str
affected_activities: List[str]
original_completion: str
revised_completion: str
days_impacted: int
mitigation_plan: str
sender_name: str
sender_title: str
def generate_delay_notice_email(delay: DelayNotice) -> dict:
"""Generate formal delay notice email."""
subject = f"NOTICE OF DELAY - {delay.project_name} - {delay.days_impacted} Days"
activities = "\n".join(f" - {a}" for a in delay.affected_activities)
body = f"""NOTICE OF DELAY
**Project:** {delay.project_name}
**Contract No:** {delay.contract_number}
**Date:** {datetime.now().strftime('%B %d, %Y')}
---
Dear Owner/Owner's Representative,
In accordance with the contract requirements, this letter serves as formal notice of a delay to the project schedule.
**Delay Classification:** {delay.delay_type}
**Cause of Delay:**
{delay.cause}
**Affected Activities:**
{activities}
**Schedule Impact:**
- Original Completion Date: {delay.original_completion}
- Revised Completion Date: {delay.revised_completion}
- Calendar Days Impacted: {delay.days_impacted}
**Mitigation Plan:**
{delay.mitigation_plan}
We request a meeting to discuss this matter and coordinate recovery efforts. Please contact us at your earliest convenience.
This notice is provided without prejudice to any rights or remedies available under the contract.
Respectfully,
{delay.sender_name}
{delay.sender_title}
"""
return {
'subject': subject,
'body': body,
'priority': 'high',
'read_receipt': True,
'delivery_receipt': True
}
邮件发送集成
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
class ConstructionEmailSender:
"""Send construction emails via SMTP."""
def __init__(self, smtp_server: str, smtp_port: int, username: str, password: str):
self.smtp_server = smtp_server
self.smtp_port = smtp_port
self.username = username
self.password = password
def send(self, to: List[str], email_data: dict, from_addr: str = None):
"""Send email with optional attachments."""
msg = MIMEMultipart()
msg['From'] = from_addr or self.username
msg['To'] = ', '.join(to)
msg['Subject'] = email_data['subject']
if email_data.get('cc'):
msg['Cc'] = ', '.join(email_data['cc'])
if email_data.get('priority') == 'high':
msg['X-Priority'] = '1'
msg.attach(MIMEText(email_data['body'], 'plain'))
# Add attachments
for attachment_path in email_data.get('attachments', []):
with open(attachment_path, 'rb') as f:
part = MIMEApplication(f.read())
part.add_header('Content-Disposition', 'attachment',
filename=attachment_path.split('/')[-1])
msg.attach(part)
# Send
with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
server.starttls()
server.login(self.username, self.password)
recipients = to + email_data.get('cc', [])
server.sendmail(msg['From'], recipients, msg.as_string())
与 DDC 流水线集成
# Example: Auto-generate RFI response email from RFI log
import pandas as pd
# Load RFI log
rfi_log = pd.read_excel("RFI_Log.xlsx")
# Get pending RFI
pending_rfi = rfi_log[rfi_log['status'] == 'Response Ready'].iloc[0]
# Generate email
rfi = RFIResponse(
rfi_number=pending_rfi['rfi_number'],
project_name=pending_rfi['project'],
subject=pending_rfi['subject'],
question=pending_rfi['question'],
response=pending_rfi['response'],
responder_name='John Smith',
responder_title='Project Architect',
attachments=['SK-001.pdf']
)
email_data = generate_rfi_response_email(rfi)
print(f"Subject: {email_data['subject']}")
print(email_data['body'])
邮件模板库
常见建筑施工邮件模板:
| 模板 | 使用场景 |
|---|---|
| RFI 回复 | 回复信息请求 |
| 送审文件传递 | 发送送审文件以供审查 |
| 会议通知 | OAC、分包商、安全会议 |
| 变更单 | CO 通知和审批 |
| 每日报告 | 每日报告分发 |
| 延误通知 | 正式延误通知 |
| 付款申请 | 提交付款申请 |
| 缺陷清单 | 缺陷清单条目通知 |
| 收尾 | 保修和收尾文件 |
资源
- 专业邮件写作:邮件应简洁明了,并以行动为导向
- 建筑施工邮件最佳实践:务必注明项目名称和参考编号
- 法律注意事项:延误通知可能有合同要求
评论
支持 Markdown