config = $config; $this->pdf = $pdf; } public function setRecipients(array $to): void { $this->to = $to; } public function setSubject(string $subject): void { $this->subject = $subject; } public function setAttachment(string $path): void { // @TODO - add some error handling. $this->attachment = $path; } public function getProperty(string $property) { // Only for simple value properies - string and numbers. // from, to, subject. if (! isset($this->{$property})) { $value = $this->config->get('email.' . $property, false); if (! $value) { $value = readline("Property {$property} is not configured. Enter value: "); } $this->{$property} = $value; } return $this->{$property}; } protected function getRecipients() { if (! isset($this->to)) { $value = $this->config->get('email.to', false); if (! $value) { $value = explode(',', readline('Provide recipients\' emails separated by a comma: ')); } $this->to = $value; } return $this->to; } private function readPassword($prompt = "Enter Password:") { echo $prompt; system('stty -echo'); $password = trim(fgets(STDIN)); system('stty echo'); return $password; } protected function getPasswordProperty() { if (! isset($this->password)) { $value = $this->config->get('email.password', false); if (! $value) { $value = $this->readPassword(); } $this->password = $value; } return $this->password; } public function sendMail(string $from, array $to, string $subject, string $text, array $attachment = []): void { $email = new Email(); $email->from($from); $email->to(...$to); // @TODO use twig for templates. Create new template service. // https://github.com/symfony/mailer $email->subject($subject); $email->text($text); if (! empty($attachment)) { if (! isset($attachment['path'])) { var_dump('Attachment path missing!'); } else { $email->attachFromPath($attachment['path'], $attachment['name'] ?? null, $attachment['type'] ?? null); } } // Not sure whether it would be nicer to use class property instead of variable. $transport = $this->getTransport(); $mailer = $this->getMailer($transport); $mailer->send($email); } public function getTransport() { // @TODO remove username and password from config. $username = rawurlencode($this->getProperty('username')); $password = rawurlencode($this->getPasswordProperty()); // If your credentials contain special characters, you must URL-encode them. // $mailer_dsn = "gmail+smtp://{$username}:{$password}@default"; $mailer_dsn = "gmail://{$username}:{$password}@localhost?encryption=tls&auth_mode=oauth"; return Transport::fromDsn($mailer_dsn); } public function getMailer($transport) { return new Mailer($transport); } public function sendDefaultMail(string $output): void { $tokens = $this->pdf->gatherTokensForTemplate( $this->getEmailTemplatePath(), false, $this->getDefaultTokens(), 'email.tokens' ); $text = $this->pdf->replaceTokensInTemplate($this->getEmailTemplatePath(), $tokens); $this->sendMail( $this->getProperty('from'), $this->getProperty('to'), $this->getProperty('subject'), $text, ['path' => $output, 'Invoice', 'application/pdf'] ); } public function getDefaultTokens(): array { $tokens = []; $date = strtotime('-1 month'); $tokens['month'] = date('F', $date); $tokens['year'] = date('Y', $date); return $tokens; } protected function getEmailTemplatePath(): ?string { if (! isset($this->templatePath)) { $template_path = $this->config->get('email.template_path', false); if (! $template_path) { $template_path = readline('Enter template file path: '); } if (! file_exists($template_path)) { throw new Exception('Template file not found!'); } $this->templatePath = $template_path; } return $this->templatePath; } public function setEmailTemplatePath(string $path): void { if (file_exists($path)) { $this->templatePath = $path; return; } throw new Exception('Email template file not found!'); } }