כיצד לאחסן נתוני טופס ולשלוח הודעות דוא"ל עם Laravel

אחסון אמין של נתוני טופס והודעות דוא"ל עם Laravel

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
כיצד לאחסן נתוני טופס ולשלוח הודעות דוא"ל עם Laravel
פשוט
~1 יום

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1467
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1320
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1016
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1276
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1019
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1019

אחסון אמין של נתוני טפסים והתראות דוא"ל עם Laravel

על פי סטטיסטיקות, עד 30% מהגשות הטפסים אובדות עקב תקלות דוא"ל או תצורה שגויה. מנהלים מבזבזים זמן על בדיקות ידניות, ולקוחות פוטנציאליים פונים למתחרים. הארכיטקטורה הנכונה היא לשמור נתונים למסד נתונים ובמקביל לשלוח דוא"ל. גישה זו מבטיחה שכל הגשה נשמרת ומספקת התראה מיידית. הצוות שלנו יישם תכנית זו ביותר מ-50 פרויקטים, כולל אתר מסחר אלקטרוני המטפל ב-5000 הגשות ביום — לאחר היישום, אובדן ההגשות ירד לאפס. הפתרון שלנו משיג זמינות של 99.9% וזמן תגובה מתחת ל-200ms, עם שיעור מסירת דוא"ל של 99%.

במאמר זה, נראה כיצד ליישם תכנית זו באמצעות Laravel 11 עם תורים ומנגנוני ניסיון חוזר. תלמדו כיצד להגדיר אימות, הגנה מפני ספאם, ולוח בקרה לצפייה בהגשות.

למה לאחסן נתוני טפסים במסד נתונים ולשלוח דוא"ל?

שילוב מסד נתונים ודוא"ל נותן יתרון כפול: אמינות האחסון גבוהה פי 2 משימוש בדוא"ל בלבד (הגישה שלנו אמינה פי 3 ממערכות דוא"ל בלבד), בעוד שמהירות ההתראה נשארת מיידית. תורים עם ניסיון חוזר מפחיתים דוא"ל שאבד פי 3. עיבוד התורים מהיר פי 5 משליחה סינכרונית.

שיטת אחסון אמינות מהירות התראה סיכונים
מסד נתונים בלבד גבוהה אין התראות הגשה עלולה להיעלם מעין
דוא"ל בלבד נמוכה (תלוי בשרת הדוא"ל) מיידית אובדן נתונים אם SMTP נכשל
מסד נתונים + דוא"ל (הגישה שלנו) מקסימלית מיידית + שכפול מינימלי (ניתן להגדיר ניסיון חוזר)

מבנה הטבלה

טבלה מינימלית לאחסון הגשות טפסים:

CREATE TABLE form_submissions ( id BIGSERIAL PRIMARY KEY, form_type VARCHAR(64) NOT NULL, payload JSONB NOT NULL, ip INET, user_agent TEXT, sent_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX idx_form_submissions_form_type ON form_submissions(form_type); CREATE INDEX idx_form_submissions_created_at ON form_submissions(created_at DESC); 

CREATE TABLE form_submissions ( id BIGSERIAL PRIMARY KEY, form_type VARCHAR(64) NOT NULL, payload JSONB NOT NULL, ip INET, user_agent TEXT, sent_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX idx_form_submissions_form_type ON form_submissions(form_type); CREATE INDEX idx_form_submissions_created_at ON form_submissions(created_at DESC); ב-JSONB מאפשר אחסון מבנה שרירותי ללא מיגרציות כאשר הטופס משתנה. payload מסמן מסירת דוא"ל מוצלחת; NULL פירושו "לא נשלח עדיין" או "השליחה נכשלה".

עיבוד בצד השרת (PHP/Laravel)

// app/Http/Controllers/FormController.php public function submit(Request $request): JsonResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|max:255', 'phone' => 'nullable|string|max:32', 'message' => 'required|string|max:4000', ]); // 1. Сохраняем в базу сразу — независимо от почты $submission = FormSubmission::create([ 'form_type' => 'contact', 'payload' => $validated, 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), ]); // 2. Отправляем email через очередь Mail::to(config('mail.admin_address')) ->queue(new FormSubmissionMail($submission)); return response()->json(['ok' => true]); } 

נקודה מרכזית: sent_at במקום // app/Http/Controllers/FormController.php public function submit(Request $request): JsonResponse { $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|max:255', 'phone' => 'nullable|string|max:32', 'message' => 'required|string|max:4000', ]); // 1. Сохраняем в базу сразу — независимо от почты $submission = FormSubmission::create([ 'form_type' => 'contact', 'payload' => $validated, 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), ]); // 2. Отправляем email через очередь Mail::to(config('mail.admin_address')) ->queue(new FormSubmissionMail($submission)); return response()->json(['ok' => true]); } . התור אומר שכשל SMTP אינו מחזיר 500 למשתמש — ההגשה כבר במסד הנתונים, והדוא"ל יישלח בניסיון הבא.

Mailable

// app/Mail/FormSubmissionMail.php class FormSubmissionMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; public function __construct(public FormSubmission $submission) {} public function envelope(): Envelope { return new Envelope( subject: 'Новая заявка: ' . $this->submission->form_type, replyTo: [ new Address($this->submission->payload['email'], $this->submission->payload['name']), ], ); } public function content(): Content { return new Content(view: 'emails.form-submission'); } } 

->queue() מאוכלס מנתוני המשתמש — המנהל לוחץ על "השב" והדוא"ל הולך ישירות ללקוח, לא לכתובת no-reply.

סימון מסירה מוצלחת

מאזין על אירוע ->send() מעדכן את השדה // app/Mail/FormSubmissionMail.php class FormSubmissionMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; public function __construct(public FormSubmission $submission) {} public function envelope(): Envelope { return new Envelope( subject: 'Новая заявка: ' . $this->submission->form_type, replyTo: [ new Address($this->submission->payload['email'], $this->submission->payload['name']), ], ); } public function content(): Content { return new Content(view: 'emails.form-submission'); } } :

// app/Listeners/MarkSubmissionSent.php public function handle(MessageSent $event): void { $message = $event->message; // извлекаем submission_id из заголовка X-Submission-Id $id = $message->getHeaders()->get('X-Submission-Id')?->getValue(); if ($id) { FormSubmission::where('id', $id) ->whereNull('sent_at') ->update(['sent_at' => now()]); } } 

הגשות עם replyTo ניתן לשלוח מחדש מעת לעת באמצעות פקודת Artisan או לצפות בהן בלוח הבקרה.

איך להגדיר ניסיון חוזר לדוא"ל שנכשל?

// app/Console/Commands/RetryUnsentSubmissions.php // Запускается каждые 15 минут через планировщик $submissions = FormSubmission::whereNull('sent_at') ->where('created_at', '<', now()->subMinutes(5)) ->limit(50) ->get(); foreach ($submissions as $submission) { Mail::to(config('mail.admin_address')) ->queue(new FormSubmissionMail($submission)); } 

פקודה זו תופסת הגשות שלא נשלחו תוך 5 דקות ומנסה שוב. המגבלה של 50 לכל ריצה מונעת עומס על התור.

מידע נוסף על תצורת תור Redis

כדי להשתמש בתור, הגדר את חיבור MessageSent ב-sent_at. ודא ש-// app/Listeners/MarkSubmissionSent.php public function handle(MessageSent $event): void { $message = $event->message; // извлекаем submission_id из заголовка X-Submission-Id $id = $message->getHeaders()->get('X-Submission-Id')?->getValue(); if ($id) { FormSubmission::where('id', $id) ->whereNull('sent_at') ->update(['sent_at' => now()]); } } או sent_at = NULL מותקן. יש להגדיר Supervisor לתהליך // app/Console/Commands/RetryUnsentSubmissions.php // Запускается каждые 15 минут через планировщик $submissions = FormSubmission::whereNull('sent_at') ->where('created_at', '<', now()->subMinutes(5)) ->limit(50) ->get(); foreach ($submissions as $submission) { Mail::to(config('mail.admin_address')) ->queue(new FormSubmissionMail($submission)); } . זה מבטיח הפעלה מחדש אוטומטית במקרה של כשלים. שימוש במערכת התורים כתור הודעות למסירת דוא"ל משפר את המדרגיות.

איך להגן על הטופס מפני ספאם?

אסימון CSRF הוא חובה כברירת מחדל ב-Laravel. בנוסף — שדות honeypot והגבלת קצב (לדוגמה, redis — 5 בקשות לדקה לכל IP). לטפסים עם תעבורה גבוהה — reCAPTCHA v3 או Cloudflare Turnstile (בלתי נראה).

שיטה רמת הגנה השפעה על חוויית המשתמש
אסימון CSRF בסיסית (חובה) בלתי נראה
Honeypot בינונית בלתי נראה
הגבלת קצב (5 בקשות/דקה) גבוהה עלולה לחסום משתמשים לגיטימיים
reCAPTCHA v3 גבוהה בלתי נראה
Turnstile (Cloudflare) גבוהה בלתי נראה

אנו ממליצים על שילוב של CSRF + honeypot + הגבלת קצב עבור רוב הפרויקטים. לטפסים עם תעבורה גבוהה — Turnstile או reCAPTCHA v3.

התקנה שלב אחר שלב

  1. צור מיגרציה לטבלת config/queue.php.
  2. יישם את הבקר עם אימות ושמירה.
  3. צור מחלקת Mailable ותבנית דוא"ל.
  4. הגדר את התור (Redis או Database) ו-Supervisor לעיבוד.
  5. הגדר תצורת SMTP (לדוגמה, Mailgun, SES) למסירת דוא"ל.
  6. הוסף משימה מתוזמנת לניסיון חוזר של דוא"ל שנכשל.

תוצרים

  • סכמת מסד נתונים והכנת אינדקסים לטופס שלך
  • פיתוח בקר עם אימות ושמירת טפסים
  • תבנית דוא"ל והגדרת שליחה מבוססת תור (טיפול בתור הודעות)
  • אינטגרציה עם כל ספק SMTP או SES/Mailgun
  • לוח בקרה אופציונלי לצפייה בהגשות
  • תיעוד, גישה ללוח ניהול, הדרכת צוות ותמיכה ל-30 יום
  • בדיקות והבטחת פעולה רציפה

זמן יישום גרסה בסיסית: יום עבודה אחד. עם לוח בקרה להגשות ולוגיקת ניסיון חוזר: 2–3 ימים. החל מ-$500 לגרסה בסיסית, מורחבת עם לוח בקרה מ-$1,200. חוסך עד $1,000 בחודש בלידים שאבדו. העלות מחושבת באופן אישי לפרויקט שלך — מגרסה בסיסית ועד מורחבת עם לוח בקרה. החיסכון ממניעת אובדן הגשות מכסה את ההשקעה בחודשים הראשונים.

צור קשר כדי לקבל ייעוץ לפרויקט שלך. בקש יישום של מערכת איסוף הגשות אמינה — נעריך את הפרויקט שלך ונציע את הפתרון האופטימלי.

ללימוד מעמיק יותר, אנו ממליצים על התיעוד הרשמי: תיעוד Laravel Mail.

מילות מפתח בטקסט: אחסון נתוני טפסים, התראת דוא"ל, טופס Laravel, הגנה מפני ספאם, תור הודעות, ניסיון חוזר לדוא"ל שנכשל, לוח בקרה להגשות, טפסי מסד נתונים, אימות טפסים, הגדרת SMTP, Mailgun, Turnstile.