Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 89
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AI
0.00% covered (danger)
0.00%
0 / 89
0.00% covered (danger)
0.00%
0 / 4
506
0.00% covered (danger)
0.00%
0 / 1
 __construct
n/a
0 / 0
n/a
0 / 0
1
 send_email
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 1
182
 isEmailValid
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 isValidHtml
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 isValidEmailSubject
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace App\Http\Controllers;
4
5use Illuminate\Http\Request;
6use Illuminate\Support\Facades\Log;
7use Illuminate\Support\Facades\Validator;
8
9class AI extends Controller
10{
11    public function __construct() {}
12
13    public function send_email(Request $request)
14    {
15
16        try {
17
18            $data = $request->all();
19
20            $body = '';
21            $subject = '';
22
23            $validator = Validator::make($data, [
24                'email' => ['required', 'email'],
25                'subject' => ['required'],
26                'body' => ['required'],
27            ]);
28
29            if ($validator->fails()) {
30                if ($validator->errors()->has('email')
31                    && ! $request->has('email')) {
32
33                    return response()->json([
34                        'status' => 'error',
35                        'message' => 'Missing required field: email',
36                        'code' => 'MISSING_FIELD',
37                    ], 400);
38                }
39
40                if (! $this->isEmailValid($data['email'])) {
41                    return response([
42                        'status' => 'error',
43                        'message' => 'Invalid email address format!',
44                        'code' => 'INVALID_EMAIL',
45                    ], 400);
46                }
47
48                if ($validator->errors()->has('subject')
49                    && ! $request->has('subject')) {
50
51                    return response()->json([
52                        'status' => 'error',
53                        'message' => 'Missing required field: subject',
54                        'code' => 'MISSING_FIELD',
55                    ], 400);
56                }
57
58                if (! $this->isValidEmailSubject($data['subject'])) {
59                    return response([
60                        'status' => 'error',
61                        'message' => 'Invalid email subject!',
62                        'code' => 'INVALID_SUBJECT',
63                    ], 400);
64                }
65
66                if ($validator->errors()->has('body')
67                    && ! $request->has('body')) {
68
69                    return response()->json([
70                        'status' => 'error',
71                        'message' => 'Missing required field: body',
72                        'code' => 'MISSING_FIELD',
73                    ], 400);
74                }
75
76                if (! $this->isValidHtml($data['body'])) {
77                    return response()->json([
78                        'status' => 'error',
79                        'message' => 'Invalid HTML!',
80                        'code' => 'INVALID_BODY',
81                    ], 422);
82                }
83            }
84
85            $toEmail = $data['email'];
86            $body = $data['body'];
87            $subject = $data['subject'];
88
89            $mail = new \SendGrid\Mail\Mail;
90
91            $mail->setFrom('fire@fire.es', 'Fire Service Titan');
92            $mail->addTo($toEmail);
93            $mail->setSubject($subject);
94            $mail->addContent('text/html', $body);
95
96            $sendgrid = new \SendGrid(env('SENDGRID_API_KEY'));
97
98            Log::channel('email_log')->info(print_r($data, true));
99
100            $response = $sendgrid->send($mail);
101            if ($response->statusCode() == 202) {
102                return response([
103                    'status' => 'success',
104                    'message' => 'Verification email sent successfully!',
105                    'email' => $toEmail,
106                ], 200);
107            }
108
109            return response([
110                'status' => 'error',
111                'message' => 'Failed to send email. Please try again later.',
112                'code' => 'EMAIL_DELIVERY_FAILED',
113            ], 500);
114
115        } catch (\Exception $e) {
116            /** @disregard P1014 */
117            $e->exceptionCode = 'SEND_VERIFICATION_EMAIL_EXCEPTION';
118            report($e);
119
120            return response(['message' => 'KO', 'error' => $e->getMessage()]);
121        }
122
123    }
124
125    public function isEmailValid($email)
126    {
127
128        $pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/';
129
130        if (preg_match($pattern, $email)) {
131            return true;
132        } else {
133            return false;
134        }
135
136    }
137
138    private function isValidHtml($html)
139    {
140        libxml_use_internal_errors(true);
141
142        $dom = new \DOMDocument;
143        $isValid = $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
144
145        libxml_clear_errors();
146
147        return $isValid;
148    }
149
150    public function isValidEmailSubject(string $subject): bool
151    {
152        $subject = trim($subject);
153
154        if ($subject === '' || mb_strlen($subject) < 3 || mb_strlen($subject) > 150) {
155            return false;
156        }
157
158        if (preg_match('/[\r\n]/', $subject)) {
159            return false;
160        }
161
162        return true;
163    }
164}