Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ush 1164 - Gmail settings #4918

Merged
merged 18 commits into from
Apr 17, 2024
2 changes: 2 additions & 0 deletions config/data-provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
'incoming_security' => '',
'incoming_username' => '',
'incoming_password' => '',
'incoming_unread_only' => 'Unread',
'incoming_last_uid' => '0'
],
'twilio' => [],
'smssync' => [],
Expand Down
3 changes: 2 additions & 1 deletion src/Ushahidi/DataSource/DataSourceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ protected function createEmailSource(array $config)
return new Email\Email(
$config,
app('mailer'),
app(MessageRepository::class)
app(MessageRepository::class),
$this->configRepo
);
}

Expand Down
52 changes: 48 additions & 4 deletions src/Ushahidi/DataSource/Email/Email.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Ushahidi\DataSource\Contracts\IncomingDataSource;
use Ushahidi\DataSource\Concerns\MapsInboundFields;
use Ushahidi\Contracts\Repository\Entity\MessageRepository;
use Ushahidi\Contracts\Repository\Entity\ConfigRepository;
use Ushahidi\DataSource\Contracts\MessageType;

class Email extends OutgoingEmail implements IncomingDataSource
Expand All @@ -26,21 +27,25 @@ class Email extends OutgoingEmail implements IncomingDataSource
protected $config;
protected $mailer;
protected $messageRepo;
protected $configRepo;

/**
* Constructor function for DataSource
* @param array $config
* @param Mailer|null $mailer
* @param MessageRepository|null $messageRepo
* @param ConfigRepository|null $configRepo
*/
public function __construct(
array $config,
Mailer $mailer = null,
MessageRepository $messageRepo = null
MessageRepository $messageRepo = null,
ConfigRepository $configRepo = null
) {
$this->config = $config;
$this->mailer = $mailer;
$this->messageRepo = $messageRepo;
$this->configRepo = $configRepo;
}

public function getName()
Expand Down Expand Up @@ -104,6 +109,17 @@ public function getOptions()
'description' => '',
'placeholder' => 'Email account password',
'rules' => ['required']
],
'incoming_all_unread' => [
'label' => 'Fetch Emails',
'input' => 'radio',
'description' => 'Fetch every email from the inbox, or only unread.',
'options' => ['All', 'Unread'],
'rules' => ['required']
],
'incoming_last_uid' => [
'label' => '',
'input' => 'hidden',
]
];
}
Expand Down Expand Up @@ -154,14 +170,17 @@ public function fetch($limit = false)
$encryption = $this->config['incoming_security'] ?? '';
$username = $this->config['incoming_username'] ?? '';
$password = $this->config['incoming_password'] ?? '';
$unread_only = $this->config['incoming_all_unread'] ?? 'Unread';
$last_uid = $this->config['incoming_last_uid'] ?? '';
$new_last_uid = 0;

// Encryption type
$encryption = (strcasecmp($encryption, 'none') != 0) ? '/'.$encryption : '';

// To connect to an SSL IMAP or POP3 server with a self-signed certificate,
// add /novalidate-cert after the encryption protocol specification:
$no_cert_validation = !empty($encryption) ? '/novalidate-cert' : '';

try {
// Try to connect
$inbox = '{'.$server.':'.$port.'/'.$type.$encryption.$no_cert_validation.'}INBOX';
Expand All @@ -173,7 +192,7 @@ public function fetch($limit = false)
// Return on connection error
if (! $connection || $errors || $alerts) {
$errors = is_array($errors) ? implode(', ', $errors) : "";
$alerts = is_array($alerts) ? implode(', ', $errors) : "";
$alerts = is_array($alerts) ? implode(', ', $alerts) : "";
Log::info("Could not connect to incoming email server", compact('errors', 'alerts'));
return [];
}
Expand All @@ -182,7 +201,11 @@ public function fetch($limit = false)

Log::info("Connected to $inbox", [$mailboxinfo]);

$last_uid = $this->messageRepo->getLastUID('email');
// Allow an existing installation to transition to config based without forcing the platform to download everything again.
if ($last_uid == '') {
$last_uid = $this->messageRepo->getLastUID('email');
}

if ($last_uid > 0) {
$max_range = $last_uid + $limit;
$search_string = $last_uid ? $last_uid + 1 . ':' . $max_range : '1:' . $max_range;
Expand All @@ -208,6 +231,10 @@ public function fetch($limit = false)
break;
}

if ($unread_only == 'Unread' and $email->seen == 1) {
continue;
}

$message = $html_message = "";
$structure = imap_fetchstructure($connection, $email->uid, FT_UID);

Expand Down Expand Up @@ -235,9 +262,16 @@ public function fetch($limit = false)
$message = imap_qprint($message);
$messages[] = $this->processIncoming($email, $message);
}
if (isset($email->uid)) {
$new_last_uid = isset($email->uid) ? $email->uid : null;
}
}
}

if ($new_last_uid && $new_last_uid != $last_uid) {
$this->updateLastUid($this->config, $new_last_uid);
}

imap_errors();
imap_alerts();

Expand All @@ -253,6 +287,16 @@ public function fetch($limit = false)
return $messages;
}

private function updateLastUid($config, $last_uid)
{
$providerConfig = $this->configRepo->get('data-provider');
$config['incoming_last_uid'] = $last_uid;
$providerConfigArray = $providerConfig->asArray();
$providerConfigArray[$this->getId()] = $config;
$providerConfig->setState($providerConfigArray);
$this->configRepo->update($providerConfig);
}

/**
* Process individual incoming email
*
Expand Down
24 changes: 22 additions & 2 deletions tests/Unit/DataSource/EmailDataSourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use phpmock\mockery\PHPMockery;
use Ushahidi\Tests\TestCase;
use Ushahidi\Contracts\Repository\Entity\MessageRepository;
use Ushahidi\Contracts\Repository\Entity\ConfigRepository;
use Ushahidi\Core\Entity\Config;
use Ushahidi\DataSource\Email\Email;
use Ushahidi\Multisite\Site;

Expand Down Expand Up @@ -51,10 +53,13 @@ public function testSend()
$this->app->make('multisite')->setSite($site);

$mockMailer = M::mock(\Illuminate\Contracts\Mail\Mailer::class);
$mockConfigRepo = M::mock(ConfigRepository::class);

$email = new Email(
[],
$mockMailer
$mockMailer,
null,
$mockConfigRepo
);

$mockMailer->shouldReceive('send')->once()->with(
Expand Down Expand Up @@ -92,6 +97,19 @@ public function testFetch()

$mockMessageRepo->shouldReceive('getLastUID')->once()->andReturn(712);

$mockConfigRepo = M::mock(ConfigRepository::class);
$mockConfigRepo->shouldReceive('get')->once()->andReturn(new Config([
'incoming_type' => 'imap',
'incoming_server' => 'imap.somewhere.com',
'incoming_port' => '993',
'incoming_security' => 'ssl',
'incoming_username' => 'someuser',
'incoming_password' => 'mypassword',
'incoming_all_unread' => 'All',
'incoming_last_uid' => '712'
]));
$mockConfigRepo->shouldReceive('update')->once()->andReturnUndefined();

$email = new Email(
[
'incoming_type' => 'imap',
Expand All @@ -100,9 +118,11 @@ public function testFetch()
'incoming_security' => 'ssl',
'incoming_username' => 'someuser',
'incoming_password' => 'mypassword',
'incoming_all_unread' => 'All',
],
$mockMailer,
$mockMessageRepo
$mockMessageRepo,
$mockConfigRepo
);

$mockImapOpen = PHPMockery::mock("Ushahidi\DataSource\Email", 'imap_open');
Expand Down
2 changes: 1 addition & 1 deletion tests/datasets/ushahidi/Base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2198,7 +2198,7 @@ config:
-
group_name: "data-provider"
config_key: email
config_value: '{"incoming_type":"","incoming_server":"","incoming_port":"","incoming_security":"","incoming_username":"","incoming_password":""}'
config_value: '{"incoming_type":"","incoming_server":"","incoming_port":"","incoming_security":"","incoming_username":"","incoming_password":"","incoming_all_unread":"","incoming_last_uid":""}'
-
group_name: "data-provider"
config_key: frontlinesms
Expand Down
Loading