aerc sendmail wip
This commit is contained in:
152
sendmail
Executable file
152
sendmail
Executable file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Sendmail-compatible wrapper for Microsoft Graph email sending.
|
||||
Queues emails in maildir format for processing by the sync daemon.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
from email.parser import Parser
|
||||
from email.utils import parseaddr
|
||||
|
||||
# Add the project root to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from src.utils.mail_utils.helpers import ensure_directory_exists
|
||||
|
||||
|
||||
def extract_org_from_email(email_address: str) -> str:
|
||||
"""
|
||||
Extract organization name from email address domain.
|
||||
|
||||
Args:
|
||||
email_address: Email address like "user@corteva.com"
|
||||
|
||||
Returns:
|
||||
Organization name (e.g., "corteva")
|
||||
"""
|
||||
if "@" not in email_address:
|
||||
return "default"
|
||||
|
||||
domain = email_address.split("@")[1].lower()
|
||||
|
||||
# Map known domains to org names
|
||||
domain_to_org = {
|
||||
"corteva.com": "corteva",
|
||||
# Add more domain mappings as needed
|
||||
}
|
||||
|
||||
return domain_to_org.get(domain, domain.split(".")[0])
|
||||
|
||||
|
||||
def create_outbox_structure(base_path: str, org: str):
|
||||
"""
|
||||
Create maildir structure for outbox.
|
||||
|
||||
Args:
|
||||
base_path: Base maildir path (e.g., ~/Mail)
|
||||
org: Organization name
|
||||
"""
|
||||
org_path = os.path.join(base_path, org, "outbox")
|
||||
ensure_directory_exists(os.path.join(org_path, "new"))
|
||||
ensure_directory_exists(os.path.join(org_path, "cur"))
|
||||
ensure_directory_exists(os.path.join(org_path, "tmp"))
|
||||
ensure_directory_exists(os.path.join(org_path, "failed"))
|
||||
|
||||
|
||||
def queue_email(email_content: str, org: str) -> bool:
|
||||
"""
|
||||
Queue email in maildir outbox for sending.
|
||||
|
||||
Args:
|
||||
email_content: Raw email content
|
||||
org: Organization name
|
||||
|
||||
Returns:
|
||||
True if queued successfully, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Get base maildir path
|
||||
base_path = os.path.expanduser(os.getenv("MAILDIR_PATH", "~/Mail"))
|
||||
|
||||
# Create outbox structure
|
||||
create_outbox_structure(base_path, org)
|
||||
|
||||
# Generate unique filename
|
||||
timestamp = str(int(time.time() * 1000000))
|
||||
hostname = os.uname().nodename
|
||||
filename = f"{timestamp}.{os.getpid()}.{hostname}"
|
||||
|
||||
# Write to tmp first, then move to new (atomic operation)
|
||||
tmp_path = os.path.join(base_path, org, "outbox", "tmp", filename)
|
||||
new_path = os.path.join(base_path, org, "outbox", "new", filename)
|
||||
|
||||
with open(tmp_path, "w", encoding="utf-8") as f:
|
||||
f.write(email_content)
|
||||
|
||||
os.rename(tmp_path, new_path)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to queue email: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main sendmail wrapper function.
|
||||
Reads email from stdin and queues it for sending.
|
||||
"""
|
||||
# Set up basic logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler(os.path.expanduser("~/Mail/sendmail.log")),
|
||||
]
|
||||
)
|
||||
|
||||
try:
|
||||
# Read email from stdin
|
||||
email_content = sys.stdin.read()
|
||||
|
||||
if not email_content.strip():
|
||||
logging.error("No email content received")
|
||||
sys.exit(1)
|
||||
|
||||
# Parse email to extract From header
|
||||
parser = Parser()
|
||||
msg = parser.parsestr(email_content)
|
||||
|
||||
from_header = msg.get("From", "")
|
||||
if not from_header:
|
||||
logging.error("No From header found in email")
|
||||
sys.exit(1)
|
||||
|
||||
# Extract email address from From header
|
||||
_, from_email = parseaddr(from_header)
|
||||
if not from_email:
|
||||
logging.error(f"Could not parse email address from From header: {from_header}")
|
||||
sys.exit(1)
|
||||
|
||||
# Determine organization from email domain
|
||||
org = extract_org_from_email(from_email)
|
||||
|
||||
# Queue the email
|
||||
if queue_email(email_content, org):
|
||||
logging.info(f"Email queued successfully for org: {org}, from: {from_email}")
|
||||
sys.exit(0)
|
||||
else:
|
||||
logging.error("Failed to queue email")
|
||||
sys.exit(1)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Sendmail wrapper error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user