Completed
Pull Request — master (#677)
by Will
01:49
created

EmailRecipient::canCreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
namespace SilverStripe\UserForms\Model\Recipient;
4
5
use SilverStripe\Admin\LeftAndMain;
6
use SilverStripe\Assets\FileFinder;
7
use SilverStripe\CMS\Controllers\CMSMain;
8
use SilverStripe\CMS\Controllers\CMSPageEditController;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\Email\Email;
11
use SilverStripe\Forms\CheckboxField;
12
use SilverStripe\Forms\DropdownField;
13
use SilverStripe\Forms\FieldGroup;
14
use SilverStripe\Forms\FieldList;
15
use SilverStripe\Forms\Form;
16
use SilverStripe\Forms\GridField\GridField;
17
use SilverStripe\Forms\GridField\GridFieldButtonRow;
18
use SilverStripe\Forms\GridField\GridFieldConfig;
19
use SilverStripe\Forms\GridField\GridFieldDeleteAction;
20
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
21
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
22
use SilverStripe\Forms\LiteralField;
23
use SilverStripe\Forms\TabSet;
24
use SilverStripe\Forms\TextareaField;
25
use SilverStripe\Forms\TextField;
26
use SilverStripe\ORM\ArrayList;
27
use SilverStripe\ORM\DataObject;
28
use SilverStripe\ORM\DB;
29
use SilverStripe\ORM\FieldType\DBField;
30
use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField;
31
use SilverStripe\UserForms\Model\EditableFormField;
32
use SilverStripe\UserForms\Model\EditableFormField\EditableMultipleOptionField;
33
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
34
use SilverStripe\UserForms\Model\Recipient\EmailRecipientCondition;
35
use SilverStripe\UserForms\Model\UserDefinedForm;
36
use SilverStripe\UserForms\UserForm;
37
use SilverStripe\View\Requirements;
38
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
39
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
40
41
/**
42
 * A Form can have multiply members / emails to email the submission
43
 * to and custom subjects
44
 *
45
 * @package userforms
46
 */
47
class EmailRecipient extends DataObject
48
{
49
    private static $db = [
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
50
        'EmailAddress' => 'Varchar(200)',
51
        'EmailSubject' => 'Varchar(200)',
52
        'EmailFrom' => 'Varchar(200)',
53
        'EmailReplyTo' => 'Varchar(200)',
54
        'EmailBody' => 'Text',
55
        'EmailBodyHtml' => 'HTMLText',
56
        'EmailTemplate' => 'Varchar',
57
        'SendPlain' => 'Boolean',
58
        'HideFormData' => 'Boolean',
59
        'CustomRulesCondition' => 'Enum("And,Or")'
60
    ];
61
62
    private static $has_one = [
0 ignored issues
show
Unused Code introduced by
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
63
        'Form' => DataObject::class,
64
        'SendEmailFromField' => EditableFormField::class,
65
        'SendEmailToField' => EditableFormField::class,
66
        'SendEmailSubjectField' => EditableFormField::class
67
    ];
68
69
    private static $has_many = [
0 ignored issues
show
Unused Code introduced by
The property $has_many is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
70
        'CustomRules' => EmailRecipientCondition::class,
71
    ];
72
73
    private static $owns = [
0 ignored issues
show
Unused Code introduced by
The property $owns is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
74
        'CustomRules',
75
    ];
76
77
    private static $cascade_deetes = [
0 ignored issues
show
Unused Code introduced by
The property $cascade_deetes is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
78
        'CustomRules',
79
    ];
80
81
    private static $summary_fields = [
0 ignored issues
show
Unused Code introduced by
The property $summary_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
82
        'EmailAddress',
83
        'EmailSubject',
84
        'EmailFrom'
85
    ];
86
87
    private static $table_name = 'UserDefinedForm_EmailRecipient';
0 ignored issues
show
Unused Code introduced by
The property $table_name is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
88
89
    /**
90
     * Setting this to true will allow you to select "risky" fields as
91
     * email recipient, such as free-text entry fields.
92
     *
93
     * It's advisable to leave this off.
94
     *
95
     * @config
96
     * @var bool
97
     */
98
    private static $allow_unbound_recipient_fields = false;
0 ignored issues
show
Unused Code introduced by
The property $allow_unbound_recipient_fields is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
99
100
    public function requireDefaultRecords()
101
    {
102
        parent::requireDefaultRecords();
103
104
        // make sure to migrate the class across (prior to v5.x)
105
        DB::query("UPDATE UserDefinedForm_EmailRecipient SET FormClass = 'Page' WHERE FormClass IS NULL");
106
    }
107
108
    public function summaryFields()
109
    {
110
        $fields = parent::summaryFields();
111
        if (isset($fields['EmailAddress'])) {
112
            $fields['EmailAddress'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILADDRESS', Email::class);
113
        }
114
        if (isset($fields['EmailSubject'])) {
115
            $fields['EmailSubject'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Subject');
116
        }
117
        if (isset($fields['EmailFrom'])) {
118
            $fields['EmailFrom'] = _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILFROM', 'From');
119
        }
120
        return $fields;
121
    }
122
123
    /**
124
     * Get instance of UserDefinedForm when editing in getCMSFields
125
     *
126
     * @return UserDefinedFrom
127
     */
128
    protected function getFormParent()
129
    {
130
        // LeftAndMain::sessionNamespace is protected. @todo replace this with a non-deprecated equivalent.
131
        $sessionNamespace = $this->config()->get('session_namespace') ?: LeftAndMain::class;
132
133
        $formID = $this->FormID
134
            ? $this->FormID
135
            : Controller::curr()->getRequest()->getSession()->get($sessionNamespace . '.currentPage');
136
        return UserDefinedForm::get()->byID($formID);
137
    }
138
139
    public function getTitle()
140
    {
141
        if ($this->EmailAddress) {
142
            return $this->EmailAddress;
143
        }
144
        if ($this->EmailSubject) {
145
            return $this->EmailSubject;
146
        }
147
        return parent::getTitle();
148
    }
149
150
    /**
151
     * Generate a gridfield config for editing filter rules
152
     *
153
     * @return GridFieldConfig
154
     */
155
    protected function getRulesConfig()
156
    {
157
        $formFields = $this->getFormParent()->Fields();
158
159
        $config = GridFieldConfig::create()
160
            ->addComponents(
161
                new GridFieldButtonRow('before'),
162
                new GridFieldToolbarHeader(),
163
                new GridFieldAddNewInlineButton(),
164
                new GridFieldDeleteAction(),
165
                $columns = new GridFieldEditableColumns()
166
            );
167
168
        $columns->setDisplayFields(array(
169
            'ConditionFieldID' => function ($record, $column, $grid) use ($formFields) {
170
                return DropdownField::create($column, false, $formFields->map('ID', 'Title'));
171
            },
172
            'ConditionOption' => function ($record, $column, $grid) {
173
                $options = EmailRecipientCondition::config()->condition_options;
174
                return DropdownField::create($column, false, $options);
175
            },
176
            'ConditionValue' => function ($record, $column, $grid) {
177
                return TextField::create($column);
178
            }
179
        ));
180
181
        return $config;
182
    }
183
184
    /**
185
     * @return FieldList
186
     */
187
    public function getCMSFields()
188
    {
189
        Requirements::javascript('silverstripe/userforms:client/dist/js/userforms-cms.js');
190
191
        // Determine optional field values
192
        $form = $this->getFormParent();
193
194
        // predefined choices are also candidates
195
        $multiOptionFields = EditableMultipleOptionField::get()->filter('ParentID', $form->ID);
196
197
        // if they have email fields then we could send from it
198
        $validEmailFromFields = EditableEmailField::get()->filter('ParentID', $form->ID);
199
200
        // For the subject, only one-line entry boxes make sense
201
        $validSubjectFields = ArrayList::create(
202
            EditableTextField::get()
203
                ->filter('ParentID', $form->ID)
204
                ->exclude('Rows:GreaterThan', 1)
205
                ->toArray()
206
        );
207
        $validSubjectFields->merge($multiOptionFields);
208
209
210
        // Check valid email-recipient fields
211
        if ($this->config()->get('allow_unbound_recipient_fields')) {
212
            // To address can only be email fields or multi option fields
213
            $validEmailToFields = ArrayList::create($validEmailFromFields->toArray());
214
            $validEmailToFields->merge($multiOptionFields);
215
        } else {
216
            // To address cannot be unbound, so restrict to pre-defined lists
217
            $validEmailToFields = $multiOptionFields;
218
        }
219
220
        // Build fieldlist
221
        $fields = FieldList::create(Tabset::create('Root')->addExtraClass('EmailRecipientForm'));
222
223
        // Configuration fields
224
        $fields->addFieldsToTab('Root.EmailDetails', [
225
            // Subject
226
            FieldGroup::create(
227
                TextField::create(
228
                    'EmailSubject',
229
                    _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPESUBJECT', 'Type subject')
230
                )
231
                    ->setAttribute('style', 'min-width: 400px;'),
232
                DropdownField::create(
233
                    'SendEmailSubjectFieldID',
234
                    _t(
235
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.SELECTAFIELDTOSETSUBJECT',
236
                        '.. or select a field to use as the subject'
237
                    ),
238
                    $validSubjectFields->map('ID', 'Title')
239
                )->setEmptyString('')
240
            )
241
                ->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILSUBJECT', 'Email subject')),
242
243
            // To
244
            FieldGroup::create(
245
                TextField::create(
246
                    'EmailAddress',
247
                    _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPETO', 'Type to address')
248
                )
249
                    ->setAttribute('style', 'min-width: 400px;'),
250
                DropdownField::create(
251
                    'SendEmailToFieldID',
252
                    _t(
253
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASTO',
254
                        '.. or select a field to use as the to address'
255
                    ),
256
                    $validEmailToFields->map('ID', 'Title')
257
                )->setEmptyString(' ')
258
            )
259
                ->setTitle(_t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO', 'Send email to'))
260
                ->setDescription(_t(
261
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDEMAILTO_DESCRIPTION',
262
                    'You may enter multiple email addresses as a comma separated list.'
263
                )),
264
265
266
            // From
267
            TextField::create(
268
                'EmailFrom',
269
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.FROMADDRESS', 'Send email from')
270
            )
271
                ->setDescription(_t(
272
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.EmailFromContent',
273
                    "The from address allows you to set who the email comes from. On most servers this ".
274
                    "will need to be set to an email address on the same domain name as your site. ".
275
                    "For example on yoursite.com the from address may need to be [email protected]. ".
276
                    "You can however, set any email address you wish as the reply to address."
277
                )),
278
279
280
            // Reply-To
281
            FieldGroup::create(
282
                TextField::create('EmailReplyTo', _t(
283
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.TYPEREPLY',
284
                    'Type reply address'
285
                ))
286
                    ->setAttribute('style', 'min-width: 400px;'),
287
                DropdownField::create(
288
                    'SendEmailFromFieldID',
289
                    _t(
290
                        'SilverStripe\\UserForms\\Model\\UserDefinedForm.ORSELECTAFIELDTOUSEASFROM',
291
                        '.. or select a field to use as reply to address'
292
                    ),
293
                    $validEmailFromFields->map('ID', 'Title')
294
                )->setEmptyString(' ')
295
            )
296
                ->setTitle(_t(
297
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS',
298
                    'Email for reply to'
299
                ))
300
                ->setDescription(_t(
301
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.REPLYADDRESS_DESCRIPTION',
302
                    'The email address which the recipient is able to \'reply\' to.'
303
                ))
304
        ]);
305
306
        $fields->fieldByName('Root.EmailDetails')->setTitle(_t(__CLASS__.'.EMAILDETAILSTAB', 'Email Details'));
307
308
        // Only show the preview link if the recipient has been saved.
309
        if (!empty($this->EmailTemplate)) {
310
            $pageEditController = singleton(CMSPageEditController::class);
311
            $pageEditController
312
                ->getRequest()
313
                ->setSession(Controller::curr()->getRequest()->getSession());
314
315
            $preview = sprintf(
316
                '<p><a href="%s" target="_blank" class="btn btn-outline-secondary">%s</a></p><em>%s</em>',
317
                Controller::join_links(
318
                    $pageEditController->getEditForm()->FormAction(),
319
                    "field/EmailRecipients/item/{$this->ID}/preview"
320
                ),
321
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL', 'Preview email'),
322
                _t(
323
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_DESCRIPTION',
324
                    'Note: Unsaved changes will not appear in the preview.'
325
                )
326
            );
327
        } else {
328
            $preview = sprintf(
329
                '<em>%s</em>',
330
                _t(
331
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.PREVIEW_EMAIL_UNAVAILABLE',
332
                    'You can preview this email once you have saved the Recipient.'
333
                )
334
            );
335
        }
336
337
        // Email templates
338
        $fields->addFieldsToTab('Root.EmailContent', [
339
            CheckboxField::create(
340
                'HideFormData',
341
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.HIDEFORMDATA', 'Hide form data from email?')
342
            ),
343
            CheckboxField::create(
344
                'SendPlain',
345
                _t(
346
                    'SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDPLAIN',
347
                    'Send email as plain text? (HTML will be stripped)'
348
                )
349
            ),
350
            HTMLEditorField::create(
351
                'EmailBodyHtml',
352
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODYHTML', 'Body')
353
            )
354
                ->addExtraClass('toggle-html-only'),
355
            TextareaField::create(
356
                'EmailBody',
357
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILBODY', 'Body')
358
            )
359
                ->addExtraClass('toggle-plain-only'),
360
            LiteralField::create('EmailPreview', $preview)
361
        ]);
362
363
        $templates = $this->getEmailTemplateDropdownValues();
364
365
        if ($templates) {
366
            $fields->insertBefore(
367
                DropdownField::create(
368
                    'EmailTemplate',
369
                    _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.EMAILTEMPLATE', 'Email template'),
370
                )->addExtraClass('toggle-html-only'),
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ')'
Loading history...
371
                'EmailBodyHtml'
372
            );
373
        }
374
375
        $fields->fieldByName('Root.EmailContent')->setTitle(_t(__CLASS__.'.EMAILCONTENTTAB', 'Email Content'));
376
377
        // Custom rules for sending this field
378
        $grid = GridField::create(
379
            'CustomRules',
380
            _t('SilverStripe\\UserForms\\Model\\EditableFormField.CUSTOMRULES', 'Custom Rules'),
381
            $this->CustomRules(),
382
            $this->getRulesConfig()
383
        );
384
        $grid->setDescription(_t(
385
            'SilverStripe\\UserForms\\Model\\UserDefinedForm.RulesDescription',
386
            'Emails will only be sent to the recipient if the custom rules are met. If no rules are defined, this receipient will receive notifications for every submission.'
387
        ));
388
        $fields->addFieldsToTab('Root.CustomRules', [
389
            DropdownField::create(
390
                'CustomRulesCondition',
391
                _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIF', 'Send condition'),
392
                [
393
                    'Or' => _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFOR', 'Any conditions are true'),
394
                    'And' => _t('SilverStripe\\UserForms\\Model\\UserDefinedForm.SENDIFAND', 'All conditions are true')
395
                ]
396
            ),
397
            $grid
398
        ]);
399
400
        $fields->fieldByName('Root.CustomRules')->setTitle(_t(__CLASS__.'.CUSTOMRULESTAB', 'Custom Rules'));
401
402
        $this->extend('updateCMSFields', $fields);
403
        return $fields;
404
    }
405
406
    /**
407
     * Return whether a user can create an object of this type
408
     *
409
     * @param Member $member
410
     * @param array $context Virtual parameter to allow context to be passed in to check
411
     * @return bool
412
     */
413
    public function canCreate($member = null, $context = [])
414
    {
415
        // Check parent page
416
        $parent = $this->getCanCreateContext(func_get_args());
417
        if ($parent) {
418
            return $parent->canEdit($member);
419
        }
420
421
        // Fall back to secure admin permissions
422
        return parent::canCreate($member);
423
    }
424
425
    /**
426
     * Helper method to check the parent for this object
427
     *
428
     * @param array $args List of arguments passed to canCreate
429
     * @return SiteTree Parent page instance
430
     */
431
    protected function getCanCreateContext($args)
432
    {
433
        // Inspect second parameter to canCreate for a 'Parent' context
434
        if (isset($args[1][Form::class])) {
435
            return $args[1][Form::class];
436
        }
437
        // Hack in currently edited page if context is missing
438
        if (Controller::has_curr() && Controller::curr() instanceof CMSMain) {
439
            return Controller::curr()->currentPage();
440
        }
441
442
        // No page being edited
443
        return null;
444
    }
445
446
    /**
447
     * @param Member
448
     *
449
     * @return boolean
450
     */
451
    public function canView($member = null)
452
    {
453
        if ($form = $this->Form()) {
454
            return $form->canView($member);
455
        }
456
457
        return parent::canView($member);
458
    }
459
460
    /**
461
     * @param Member
462
     *
463
     * @return boolean
464
     */
465
    public function canEdit($member = null)
466
    {
467
        if ($form = $this->Form()) {
468
            return $form->canEdit($member);
469
        }
470
471
        return parent::canEdit($member);
472
    }
473
474
    /**
475
     * @param Member
476
     *
477
     * @return boolean
478
     */
479
    public function canDelete($member = null)
480
    {
481
        return $this->canEdit($member);
482
    }
483
484
    /**
485
     * Determine if this recipient may receive notifications for this submission
486
     *
487
     * @param array $data
488
     * @param Form $form
489
     * @return bool
490
     */
491
    public function canSend($data, $form)
492
    {
493
        // Skip if no rules configured
494
        $customRules = $this->CustomRules();
495
        if (!$customRules->count()) {
496
            return true;
497
        }
498
499
        // Check all rules
500
        $isAnd = $this->CustomRulesCondition === 'And';
501
        foreach ($customRules as $customRule) {
502
            /** @var EmailRecipientCondition  $customRule */
503
            $matches = $customRule->matches($data);
504
            if ($isAnd && !$matches) {
505
                return false;
506
            }
507
            if (!$isAnd && $matches) {
508
                return true;
509
            }
510
        }
511
512
        // Once all rules are checked
513
        return $isAnd;
514
    }
515
516
    /**
517
     * Make sure the email template saved against the recipient exists on the file system.
518
     *
519
     * @param string
520
     *
521
     * @return boolean
522
     */
523
    public function emailTemplateExists($template = '')
524
    {
525
        $t = ($template ? $template : $this->EmailTemplate);
526
527
        return array_key_exists($t, $this->getEmailTemplateDropdownValues());
528
    }
529
530
    /**
531
     * Get the email body for the current email format
532
     *
533
     * @return string
534
     */
535
    public function getEmailBodyContent()
536
    {
537
        if ($this->SendPlain) {
538
            return DBField::create_field('HTMLText', $this->EmailBody)->Plain();
539
        }
540
        return DBField::create_field('HTMLText', $this->EmailBodyHtml);
541
    }
542
543
    /**
544
     * Gets a list of email templates suitable for populating the email template dropdown.
545
     *
546
     * @return array
547
     */
548
    public function getEmailTemplateDropdownValues()
549
    {
550
        $templates = [];
551
552
        $finder = new FileFinder();
553
        $finder->setOption('name_regex', '/^.*\.ss$/');
554
555
        $templateDirectory = UserDefinedForm::config()->get('email_template_directory');
556
        // Handle cases where "userforms" might not be the base module directory, e.g. in a Travis build
557
        if (!file_exists(BASE_PATH . DIRECTORY_SEPARATOR . $templateDirectory)
558
            && substr($templateDirectory, 0, 10) === 'userforms/'
559
        ) {
560
            $templateDirectory = substr($templateDirectory, 10);
561
        }
562
        $found = $finder->find(BASE_PATH . DIRECTORY_SEPARATOR . $templateDirectory);
563
564
        foreach ($found as $key => $value) {
565
            $template = pathinfo($value);
566
            $templatePath = substr(
567
                $template['dirname'] . DIRECTORY_SEPARATOR . $template['filename'],
568
                strlen(BASE_PATH) + 1
569
            );
570
571
            $defaultPrefixes = ['userforms/templates/', 'templates/'];
572
            foreach ($defaultPrefixes as $defaultPrefix) {
573
                // Remove default userforms folder if it's provided
574
                if (substr($templatePath, 0, strlen($defaultPrefix)) === $defaultPrefix) {
575
                    $templatePath = substr($templatePath, strlen($defaultPrefix));
576
                    break;
577
                }
578
            }
579
            $templates[$templatePath] = $template['filename'];
580
        }
581
582
        return $templates;
583
    }
584
585
    /**
586
     * Validate that valid email addresses are being used
587
     *
588
     * @return ValidationResult
589
     */
590
    public function validate()
591
    {
592
        $result = parent::validate();
593
        $checkEmail = [
594
            'EmailAddress' => 'EMAILADDRESSINVALID',
595
            'EmailFrom' => 'EMAILFROMINVALID',
596
            'EmailReplyTo' => 'EMAILREPLYTOINVALID',
597
        ];
598
        foreach ($checkEmail as $check => $translation) {
599
            if ($this->$check) {
600
                //may be a comma separated list of emails
601
                $addresses = explode(',', $this->$check);
602
                foreach ($addresses as $address) {
603
                    $trimAddress = trim($address);
604
                    if ($trimAddress && !Email::is_valid_address($trimAddress)) {
605
                        $error = _t(
606
                            __CLASS__.".$translation",
607
                            "Invalid email address $trimAddress"
608
                        );
609
                        $result->addError($error . " ($trimAddress)");
610
                    }
611
                }
612
            }
613
        }
614
        return $result;
615
    }
616
}
617