MCPcopy
hub / github.com/benoitc/gunicorn / send_bulk_emails

Method send_bulk_emails

examples/celery_alternative/tasks.py:96–146  ·  view source on GitHub ↗

Send bulk emails with progress streaming. This is where dirty arbiters shine over Celery - real-time progress without polling or WebSockets. Equivalent to Celery: @app.task(bind=True) def send_bulk(self, recipients, subject, body):

(self, recipients: list, subject: str,
                         body: str)

Source from the content-addressed store, hash-verified

94 }
95
96 def send_bulk_emails(self, recipients: list, subject: str,
97 body: str) -> Generator[dict, None, None]:
98 """
99 Send bulk emails with progress streaming.
100
101 This is where dirty arbiters shine over Celery - real-time
102 progress without polling or WebSockets.
103
104 Equivalent to Celery:
105 @app.task(bind=True)
106 def send_bulk(self, recipients, subject, body):
107 for i, to in enumerate(recipients):
108 send_email(to, subject, body)
109 self.update_state(state='PROGRESS',
110 meta={'current': i, 'total': len(recipients)})
111 """
112 total = len(recipients)
113 sent = 0
114 failed = 0
115
116 for i, to in enumerate(recipients):
117 try:
118 result = self.send_email(to, subject, body)
119 sent += 1
120 yield {
121 "type": "progress",
122 "current": i + 1,
123 "total": total,
124 "percent": int((i + 1) / total * 100),
125 "last_sent": to,
126 "status": "sent",
127 }
128 except Exception as e:
129 failed += 1
130 yield {
131 "type": "progress",
132 "current": i + 1,
133 "total": total,
134 "percent": int((i + 1) / total * 100),
135 "last_sent": to,
136 "status": "failed",
137 "error": str(e),
138 }
139
140 # Final summary
141 yield {
142 "type": "complete",
143 "total": total,
144 "sent": sent,
145 "failed": failed,
146 }
147
148 def stats(self) -> dict:
149 """Get worker statistics."""

Callers

nothing calls this directly

Calls 1

send_emailMethod · 0.95

Tested by

no test coverage detected