Send_Email::addGroupEmails()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
nc 1
nop 2
dl 0
loc 5
c 0
b 0
f 0
cc 1
rs 10
1
<?php
2
/**
3
 Copyright (C) 2018-2020 KANOUN Salim
4
 This program is free software; you can redistribute it and/or modify
5
 it under the terms of the Affero GNU General Public v.3 License as published by
6
 the Free Software Foundation;
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
 Affero GNU General Public Public for more details.
11
 You should have received a copy of the Affero GNU General Public Public along
12
 with this program; if not, write to the Free Software Foundation, Inc.,
13
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14
 */
15
16
/**
17
 * Email sending services for user's email notifications
18
 */
19
20
use PHPMailer\PHPMailer\PHPMailer;
0 ignored issues
show
Bug introduced by
The type PHPMailer\PHPMailer\PHPMailer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
22
Class Send_Email {
23
    
24
	private $message;
25
	private $linkpdo;
26
	private $smtp_config;
27
	public $platformName;
28
	public $adminEmail;
29
	public $corporation;
30
	public $webAddress;
31
	public $emailsDestinators;
32
	public $subject;
33
34
	public $replyTo;
35
    
36
	public function __construct(PDO $linkpdo) {
37
		$this->linkpdo=$linkpdo;
38
       
39
		$this->smtp_config=array(
40
			'useSMTP'=> GAELO_USE_SMTP,
41
			'host'=> GAELO_SMTP_HOST,
42
			'port'=> GAELO_SMTP_PORT,
43
			'user'=> GAELO_SMTP_USER,
44
			'password' => GAELO_SMTP_PASSWORD,
45
			'SMTPSecure' => GAELO_SMTP_SECURE
46
		);
47
        
48
		$this->platformName=GAELO_PLATEFORM_NAME;
49
		$this->adminEmail=GAELO_ADMIN_EMAIL;
50
		$this->corporation=GAELO_CORPORATION;
51
		$this->webAddress=GAELO_WEB_ADDRESS;
52
		$this->replyTo=GAELO_REPLY_TO;
53
		$this->emailsDestinators=[];
54
		$this->subject='GaelO Notification';
55
	}
56
57
	/**
58
	 * Set the message to send (will be included in the HTML template)
59
	 */
60
	public function setMessage(string $message) {
61
		$this->message=$message;
62
	}
63
64
	public function setSubject(String $subject) {
65
		$this->subject=$subject;
66
	}
67
68
	/**
69
	 * Send email prepared in this class
70
	 * Sender is the the admin email in the preferece database
71
	 * @param array $emails
72
	 * @param string $subject
73
	 * @param string $replyTo , optional, to allow a direct response to the user sending email
74
	 * @return string
75
	 */
76
	public function sendEmail() {
77
78
		$mail=new PHPMailer(true); // Passing `true` enables exceptions
79
		$mail->CharSet='UTF-8';
80
81
		//Recipients
82
		if ($this->smtp_config['useSMTP']) {
83
			$mail->IsSMTP(); // Set mailer to use SMTP
84
			$mail->Host=$this->smtp_config['host']; // Specify main and backup server
85
			$mail->Port=$this->smtp_config['port']; // Set the SMTP port
86
			$mail->SMTPAuth=true; // Enable SMTP authentication
87
			$mail->Username=$this->smtp_config['user']; // SMTP username
88
			$mail->Password=$this->smtp_config['password']; // SMTP password
89
			$mail->SMTPSecure=$this->smtp_config['SMTPSecure'];
90
		}else {
91
			//Add DKIM private key if exist
92
			if (file_exists($_SERVER['DOCUMENT_ROOT'].'/data/_config/dkim.private')) {
93
				$mail->DKIM_domain=GAELO_WEB_ADDRESS;
94
				$mail->DKIM_private=$_SERVER['DOCUMENT_ROOT'].'/data/_config/dkim.private';
95
				$mail->DKIM_selector='mail';
96
				$mail->DKIM_passphrase='';
97
				$mail->DKIM_identity=$mail->From;
98
			}
99
		}
100
101
		//Add Sender Name
102
		$mail->setFrom($this->adminEmail, $this->corporation, true);
103
        
104
		//Add Reply To
105
		try {
106
			$mail->addReplyTo($this->replyTo); 
107
		}catch (Exception $e) {
108
			error_log("Reply to email problem".$e->getMessage());
109
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
110
		}
111
        
112
		//Add destinators
113
		if (sizeof($this->emailsDestinators) > 1) {
114
			foreach ($this->emailsDestinators as $value) {
115
				try {
116
					$mail->addBCC($value);
117
				}catch (Exception $e) {
118
					error_log('error adding email'.$e->getMessage());
119
				}
120
			 }
121
			//Add message to mail object
122
			$this->buildMessage($mail); 
123
		}else if (sizeof($this->emailsDestinators) == 1) {
124
			//If only one add regular adress
125
			try {
126
				$mail->addAddress($this->emailsDestinators[0]);
127
				$userObject=User::getUserByEmail($this->emailsDestinators[0], $this->linkpdo);
128
				$this->buildMessage($mail, $userObject->lastName, $userObject->firstName);
129
			}catch (Exception $e) {
130
				error_log('error adding email'.$e->getMessage());
131
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
132
			}
133
134
           
135
		}
136
137
		//Content
138
		$mail->isHTML(true); // Set email format to HTML
139
		$mail->Subject=$this->corporation.' Imaging Platform -'.$this->subject;
140
		try {
141
			$answer=$mail->send();
142
			return $answer;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $answer returns the type boolean which is incompatible with the documented return type string.
Loading history...
143
		}catch (Exception $e) {
144
			error_log("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
145
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string.
Loading history...
146
		}
147
        
148
        
149
	}
150
    
151
	private function buildMessage(PHPMailer $mail, $lastName=null, $firstName=null) {
152
        
153
		if ($lastName == null && $firstName == null) {
154
			$nameString="user";
155
		}else {
156
			$nameString=$firstName.' '.$lastName;
157
		}
158
                    
159
		$messageToSend=
160
		'<!doctype html> <html lang="en">
161
            <head>
162
                <meta charset="utf-8">
163
                <title> '.$this->platformName.'</title>
164
                <style>
165
                    h1   {color: brown ; text-align: center}
166
                    a:link { color: brown; }
167
                    header { text-align: center;}
168
                    #footer-link {
169
                        width: 100%;
170
                        background-color: beige;
171
                        color: black;
172
                        text-align: center;
173
                    }
174
                    
175
                    #automatic {
176
                        font-style: italic;
177
                    }
178
179
                    #logo-gaelo {
180
                        max-height: 180px;
181
                        width: auto;
182
                    }
183
                    
184
                    #footer-contact{ color: black ; background: white ; text-align: left}
185
                    
186
                    #message { text-align: left; }
187
                </style>       
188
            </head>
189
            <body>
190
                <header class="main-header" id ="header">
191
                    <img id="logo-gaelo" src=cid:logo_gaelo alt="Banner Image"/>
192
                </header>
193
                <h1><a href="http://'.$this->webAddress.'">'.$this->platformName.'</a></h1>
194
                <div id="message"><b>Dear '.$nameString.',</b><br>'.$this->message.'</div>
195
                <div class="footer">
196
                    <p id ="footer-contact">Please contact the Imaging Department of '.$this->corporation.' for any questions (<a HREF="mailto:'.$this->adminEmail.'">'.$this->adminEmail.'</a>) <br>
197
                                Kind regards, <br>
198
                                The Imaging Department of '.$this->corporation.'. <br>
199
                    </p>
200
                    <p id="automatic">This is an automatic e-mail. Please do not reply. <br></p>
201
                    <p id="footer-link"><a href="http://'.$this->webAddress.'">'.$this->webAddress.'</a></p>
202
                </div>
203
            </body>
204
        </html>';
205
        
206
		$messageToSend=trim(preg_replace('/\t+/', '', $messageToSend));
207
		$messageToSend=str_replace(array("\r", "\n"), '', $messageToSend);
208
        
209
		//Prepare Html2PlainText for email validity (both version to enhance spam validation)
210
		$htmlMessageObject=new \Html2Text\Html2Text($messageToSend);
0 ignored issues
show
Bug introduced by
The type Html2Text\Html2Text was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
211
		$mail->Body=$messageToSend;
212
		$mail->AltBody=$htmlMessageObject->getText();
213
		$mail->AddEmbeddedImage($_SERVER['DOCUMENT_ROOT'].'/assets/images/gaelo-logo-square.png', 'logo_gaelo');
214
        
215
        
216
	}
217
    
218
	/**
219
	 * Retrieve all emails of Admins users
220
	 */
221
	public function getAdminsEmails() {
222
		$connecter=$this->linkpdo->prepare('SELECT email FROM users WHERE is_administrator=1 AND status!="Deactivated"');
223
		$connecter->execute();
224
		$adminResult=$connecter->fetchAll(PDO::FETCH_COLUMN);
225
       
226
		return $adminResult;
227
	}
228
    
229
	/**
230
	 * Get email of a given user
231
	 * @param string $username
232
	 * @return string email
233
	 */
234
	public function getUserEmails(string $username) {
235
		$userObject=new User($username, $this->linkpdo);
236
		return $userObject->userEmail;
237
	}
238
    
239
	/**
240
	 * Method to get email by role in a study
241
	 * Do not return deactivated account
242
	 * @param string $role
243
	 * @param string $study
244
	 * @return array mails
245
	 */
246
	public function getRolesEmails(string $study, string $role) {
247
		$connecter=$this->linkpdo->prepare('SELECT users.email FROM roles, users 
248
                                                     WHERE roles.study=:study 
249
                                                        AND roles.username=users.username 
250
                                                        AND roles.name=:role
251
                                                        AND users.status!="Deactivated"');
252
		$connecter->execute(array(
253
				'study'=>$study,
254
				'role'=>$role));
255
    	
256
		$results=$connecter->fetchAll(PDO::FETCH_COLUMN);
257
		return $results;
258
	}
259
260
	/**
261
	 * Return all users having a specific center in main of affiliated centers
262
	 * @param PDO $linkpdo
263
	 * @param $center
264
	 * @return User[]
265
	 */
266
	private function getUsersAffiliatedToCenter(int $center) {
267
		
268
		//Select All users that has a matching center
269
		$queryUsersEmail=$this->linkpdo->prepare('
270
								    SELECT users.username
271
									FROM users
272
									WHERE (center=:center)
273
									UNION
274
									SELECT affiliated_centers.username
275
									FROM affiliated_centers,
276
									     users
277
									WHERE (affiliated_centers.center=:center
278
									       AND affiliated_centers.username=users.username)');
279
		
280
		$queryUsersEmail->execute(array('center'=>$center));
281
		$users=$queryUsersEmail->fetchAll(PDO::FETCH_COLUMN);
282
		
283
		$usersObjects=[];
284
		foreach ($users as $user) {
285
			$usersObjects[]=new User($user, $this->linkpdo);	
286
		}
287
		
288
		return $usersObjects;
289
290
	}
291
    
292
	/**
293
	 * Add investigators emails having a particular center center in main or affiliated center
294
	 */
295
	public function selectInvestigatorsEmailsWithSameCenter(String $study, int $center, ?array $job=null) : Send_Email {
296
		//Select All users that has a matching center
297
		$users=$this->getUsersAffiliatedToCenter($center);
298
		//For each user check that we match role requirement (array if investigator), string if monitor or supervisor
299
		foreach ($users as $user) {
300
            
301
			if (is_array($job) && !in_array($user->userJob, $job)) {
302
				continue;
303
			}
304
        
305
			if ($user->isRoleAllowed($study, User::INVESTIGATOR)) {
306
				$this->addEmail($user->userEmail);
307
			}
308
            
309
		}
310
        
311
		return $this;
312
	}
313
314
	public function addAminEmails() : Send_Email {
315
316
		$emails=$this->getAdminsEmails();
317
		$this->addEmails($emails);
318
		return $this;
319
320
	}
321
322
	public function addEmails(Array $emails) : Send_Email{
323
324
		foreach ($emails as $email) {
325
			if (!in_array($email, $this->emailsDestinators))
326
			{
327
				$this->emailsDestinators[]=$email; 
328
			}
329
330
		}
331
		return $this;
332
333
	}
334
335
	public function addGroupEmails(String $study, String $role) : Send_Email {
336
337
		$emails=$this->getRolesEmails($study, $role);
338
		$this->addEmails($emails);
339
		return $this;
340
341
	}
342
343
	public function addEmailsReviewerWithNoReview(string $study, int $idVisit) {
344
		$connecter=$this->linkpdo->prepare('SELECT users.email FROM roles, users 
345
												WHERE roles.study=:study 
346
												AND roles.username=users.username 
347
												AND roles.name=:role
348
												AND users.status!="Deactivated"
349
												AND (SELECT COUNT(*) FROM reviews WHERE id_visit=:idVisit AND username=roles.username AND deleted=0 AND validated=1 AND is_local=0) = 0
350
												');
351
		$connecter->execute(array(
352
				'study'=>$study,
353
				'role'=>User::REVIEWER,
354
				'idVisit' => $idVisit));
355
    	
356
		$emails=$connecter->fetchAll(PDO::FETCH_COLUMN);
357
		$this->addEmails($emails);
358
		return $this;
359
	}
360
361
	public function addEmail(String $email) : Send_Email {
362
363
		if (!in_array($email, $this->emailsDestinators))
364
			{
365
				$this->emailsDestinators[]=$email; 
366
			}
367
        
368
		return $this;
369
	}
370
371
	public function sendModifyUserMessage($username, $newPassword) {
372
373
		$message="Your account password is reset. Please log in at: ".$this->webAddress."<br>
374
        Username : $username<br>
375
        Temporary password : $newPassword<br>
376
        You will be asked to change this password at your first log in attempt<br>
377
        on the platform.<br>";
378
        
379
		$this->setMessage($message);
380
		$this->subject='Reactivation';
381
		$this->sendEmail();
382
383
	}
384
385
	public function sendNewAccountMessage($username, $password) {
386
387
		$message="Your account is created for the upload platform used to exchange
388
                imaging data. Please log in at: " . $this->webAddress." <br>
389
                Username : $username<br>
390
                Temporary password : $password<br>
391
                You will be asked to change this password at your first log in attempt
392
                on the platform.<br><br>";
393
394
		$this->setMessage($message);
395
		$this->subject='New account';
396
		$this->sendEmail();
397
	}
398
399
	public function sendNewPasswordEmail($username, $password) {
400
401
		$message="This automatic e-mail contains your new temporary password for your
402
          user account.<br>
403
          Username : ".$username." <br>
404
          Temporary password : ".$password." <br>
405
          You will be asked to change this password at your first connection.<br>";
406
        
407
		$this->setMessage($message);
408
		$this->subject='New Password';
409
		$this->sendEmail();
410
411
	}
412
413
	public function sendQCDesicionEmail(String $controlDecision, String $study, String $patientCode, String $visitType, $formDecision, $formComment, $imageDecision, $imageComment) {
414
		$message="Quality Control of the following visit has been set to : ".$controlDecision."<br>
415
                Study : ".$study."<br>
416
                Patient Number : ".$patientCode."<br>
417
                Visit : ".$visitType."<br>
418
                Investigation Form : ".$formDecision." Comment :".$formComment."<br>
419
                Image Series : ".$imageDecision." Comment :".$imageComment." <br>";
420
421
		$this->setMessage($message);
422
		$this->subject = $study.' - Quality Control Patient '.$patientCode;
423
		$this->sendEmail();
424
	}
425
426
	public function sendBlockedAccountNoPasswordChangeEmail($username, $linkedStudy) {
427
428
		$message="The password change request cannot be done because the account is Deactivated<br>
429
          Username : ".$username."<br>
430
          The account is linked to the following studies:".implode(',', $linkedStudy)."<br>
431
          Please contact the ".$this->corporation." to activate your account:<br>
432
          ".$this->adminEmail."<br>";
433
434
		$this->setMessage($message);
435
		$this->subject='Blocked account';
436
		$this->sendEmail();
437
438
	}
439
440
	public function sendAdminLoggedAlertEmail($username, $remoteAddress) {
441
		$message='the Admin user '.$username.' logged in from '.$remoteAddress.'
442
        <br> Please review this activity';
443
		$this->setMessage($message);
444
		$this->subject="Admin Logged In";
445
		$this->sendEmail();
446
        
447
	}
448
449
	public function sendUnlockRequestMessage(String $role, String $username, String $visitType, $patientNum, String $study, String $request) {
450
		$message="An Unlock ".$role." form Request was emitted by ".$username. 
451
		" for the ".$visitType. 
452
		" visit of patient ".$patientNum. 
453
		" in Study ".$study."<br>
454
        Reason for request: " . $request." <br>";
455
		$this->setMessage($message);
456
		$this->subject='Ask Unlock';
457
		$this->sendEmail();
458
        
459
	}
460
461
	public function sendReviewReadyMessage(String $study, int $patientCode, String $visitType) {
462
		$message = "The following visit is ready for review in the platform: <br>
463
        Study : ".$study."<br>
464
        Patient Number : ".$patientCode."<br>
465
        Visit : ".$visitType."<br>";
466
		$this->setMessage($message);
467
		$this->subject=$study." - Awaiting Review Patient ".$patientCode;
468
		$this->sendEmail();
469
	}
470
471
	public function sendCorrectiveActionDoneMessage(bool $done, String $study, int $patientCode, String $visitType) {
472
473
		if (!$done) {
474
			$message="No corrective action could be applied on the following visit: <br>
475
                        Study : " . $study."<br>
476
			            Patient Number : " . $patientCode."<br>
477
			            Uploaded visit : " . $visitType."<br>";
478
		} 
479
		else {
480
			$message="A corrective action was applied on the following visit: <br>
481
                        Study : " . $study."<br>
482
		          		Patient Number : " . $patientCode."<br>
483
		          		Uploaded visit : " . $visitType."<br>";
484
			
485
		}
486
		$this->setMessage($message);
487
		$this->subject= $study." - Corrective Action Patient ".$patientCode;
488
		$this->sendEmail();
489
490
	}
491
492
	public function sendRequestMessage(String $name, String $email, String $center, String $request) {
493
		$message="The following request was sent and will be processed as soon as possible:<br>
494
		Name : ".$name."<br>
495
		E-mail : ".$email."<br>
496
		Investigational center : ".$center."<br>
497
        Request : ".$request."<br>";
498
        
499
		$this->setMessage($message);
500
		$this->subject="Request";
501
		$this->sendEmail();
502
	}
503
504
	public function sendAwaitingAdjudicationMessage(String $study, int $patientCode, String $visitType) {
505
		$message="Review of the following visit is awaiting adjudication <br>
506
        Study : ".$study."<br>
507
        Patient Number : ".$patientCode."<br>
508
        Visit : ".$visitType."<br>
509
        The visit is awaiting for your adjudication review";
510
511
		$this->setMessage($message);
512
		$this->subject= $study." - Awaiting Adjudication Patient ".$patientCode ;
513
		$this->sendEmail();
514
	}
515
516
	public function sendVisitConcludedMessage(String $study, int $patientCode, String $visitType, $conclusionValue) {
517
		$message="Review of the following visit is concluded <br>
518
                Study : ".$study."<br>
519
                Patient Number : ".$patientCode."<br>
520
				Visit : ".$visitType."<br>
521
                Conclusion Value : ".$conclusionValue;
522
523
		$this->setMessage($message);
524
		$this->subject=$study." - Visit Concluded Patient ".$patientCode;
525
		$this->sendEmail();
526
	}
527
528
	public function sendBlockedAccountNotification($username, $studies) {
529
		$message='The following user account is blocked after too many bad password
530
                attempts.<br>
531
                Username : '.$username.'<br>
532
                The account is linked to the following studies:<br>
533
                '. implode('<br>', $studies).' </br>';
534
535
		$this->setMessage($message);
536
		$this->subject="Account Blocked";
537
		$this->sendEmail();
538
	}
539
540
	public function sendUploadedVisitMessage($study, $patientCode, $visitType) {
541
		$message="The following visit has been uploaded on the platform: <br>
542
        Study : ".$study."<br>
543
        Patient Number : ".$patientCode."<br>
544
        Uploaded visit : ".$visitType."<br>";
545
546
		$this->setMessage($message);
547
		$this->subject= $study." - New upload Patient ".$patientCode;
548
		$this->sendEmail();
549
550
	}
551
552
	public function sendDeletedFormMessage(String $study, String $patientCode, String $visitType) {
553
		$message="Your form sent for study : ".$study."<br>
554
        Patient : ".$patientCode."<br>
555
        Visit  : ".$visitType." <br>
556
        Have been deleted. <br>
557
        You can now resend a new version of this form <br>";
558
559
		$this->setMessage($message);
560
		$this->subject= $study." - Form Deleted Patient ".$patientCode;
561
		$this->sendEmail();
562
563
	}
564
565
	public function sendUnlockedFormMessage(String $study, String $patientCode, String $visitType) {
566
		$message="Your form sent for study : ".$study."<br>
567
        Patient : ".$patientCode."<br>
568
        Visit  : ".$visitType." <br>
569
        Have been Unlocked. <br>
570
        You can now resend a new version of this form <br>";
571
572
		$this->setMessage($message);
573
		$this->subject= $study." - Form Unlocked Patient ".$patientCode;
574
		$this->sendEmail();
575
576
	}
577
578
	public function sendUploadValidationFailure($idVisit, $patientCode, String $visitType, String $study, String $zipPath, String $username, String $errorMessage) {
579
		$message="An Import Error occured during validation of upload <br>
580
            Visit ID : ".$idVisit."<br>
581
            Patient Code : ".$patientCode."<br>
582
            Visit Type : ".$visitType."<br>
583
            Study : ".$study."<br>
584
            zipPath : ".$zipPath."<br>
585
            username: ".$username."<br>
586
            error  : ".$errorMessage."<br>";
587
588
		$this->setMessage($message);
589
		$this->subject=$study." - Error During Import Patient ".$patientCode;
590
		$this->sendEmail();
591
	}
592
593
	public function sendCreatedNotDoneVisitNotification($patientCode, $study, $visitType, $creatorUser) {
594
		$message="A Not Done visit has been created <br>
595
        Patient Number : ".$patientCode."<br>
596
        Study : ".$study."<br> 
597
        Visit Type : ".$visitType."<br>
598
        Creating Username : ".$creatorUser."<br>";
599
600
		$this->setMessage($message);
601
		$this->subject=$study." - Visit Not Done Patient ".$patientCode;
602
		$this->sendEmail();
603
	}
604
605
    
606
}
607