Add member management for mailman
This commit is contained in:
parent
a74d0936a2
commit
904ec829c1
|
@ -3,6 +3,7 @@
|
|||
namespace App\Mailgateway\Types;
|
||||
|
||||
use App\Maildispatcher\Data\MailEntry;
|
||||
use App\Mailman\Exceptions\MailmanServiceException;
|
||||
use App\Mailman\Support\MailmanService;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
@ -28,7 +29,7 @@ class MailmanType extends Type
|
|||
|
||||
public function works(): bool
|
||||
{
|
||||
return app(MailmanService::class)->setCredentials($this->url, $this->user, $this->password)->check();
|
||||
return $this->service()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,12 +67,18 @@ class MailmanType extends Type
|
|||
|
||||
public function search(string $name, string $domain, string $email): ?MailEntry
|
||||
{
|
||||
return null;
|
||||
$list = $this->service()->getLists()->first(fn ($list) => $list->fqdnListname === "{$name}@{$domain}");
|
||||
throw_if(!$list, MailmanServiceException::class, "List for {$name}@{$domain} not found");
|
||||
$member = $this->service()->members($list)->first(fn ($member) => $member->email === $email);
|
||||
|
||||
return $member ? MailEntry::from(['email' => $member->email]) : null;
|
||||
}
|
||||
|
||||
public function add(string $name, string $domain, string $email): void
|
||||
{
|
||||
return;
|
||||
$list = $this->service()->getLists()->first(fn ($list) => $list->fqdnListname === "{$name}@{$domain}");
|
||||
throw_if(!$list, MailmanServiceException::class, "List for {$name}@{$domain} not found");
|
||||
$this->service()->addMember($list, $email);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,10 +86,23 @@ class MailmanType extends Type
|
|||
*/
|
||||
public function list(string $name, string $domain): Collection
|
||||
{
|
||||
return collect([]);
|
||||
$list = $this->service()->getLists()->first(fn ($list) => $list->fqdnListname === "{$name}@{$domain}");
|
||||
throw_if(!$list, MailmanServiceException::class, "List for {$name}@{$domain} not found");
|
||||
|
||||
return collect($this->service()->members($list)->map(fn ($member) => MailEntry::from(['email' => $member->email]))->all());
|
||||
}
|
||||
|
||||
public function remove(string $name, string $domain, string $email): void
|
||||
{
|
||||
$list = $this->service()->getLists()->first(fn ($list) => $list->fqdnListname === "{$name}@{$domain}");
|
||||
throw_if(!$list, MailmanServiceException::class, "List for {$name}@{$domain} not found");
|
||||
$member = $this->service()->members($list)->first(fn ($member) => $member->email === $email);
|
||||
throw_if(!$member, MailmanServiceException::class, 'Member for removing not found');
|
||||
$this->service()->removeMember($member);
|
||||
}
|
||||
|
||||
private function service(): MailmanService
|
||||
{
|
||||
return app(MailmanService::class)->setCredentials($this->url, $this->user, $this->password);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mailman\Data;
|
||||
|
||||
use Spatie\LaravelData\Attributes\MapName;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
||||
|
||||
#[MapName(SnakeCaseMapper::class)]
|
||||
class Member extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public string $email,
|
||||
public string $listId,
|
||||
public string $memberId,
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Mailman\Support;
|
||||
|
||||
use App\Mailman\Data\MailingList;
|
||||
use App\Mailman\Data\Member;
|
||||
use App\Mailman\Exceptions\MailmanServiceException;
|
||||
use App\Mailman\MailmanSettings;
|
||||
use Illuminate\Http\Client\ConnectionException;
|
||||
|
@ -43,26 +44,50 @@ class MailmanService
|
|||
}
|
||||
|
||||
/**
|
||||
* @return LazyCollection<int, string>
|
||||
* @return LazyCollection<int, Member>
|
||||
*/
|
||||
public function members(string $listId): LazyCollection
|
||||
public function members(MailingList $list): LazyCollection
|
||||
{
|
||||
return app(Paginator::class)->result(
|
||||
fn ($page) => $this->http()->get("/lists/{$listId}/roster/member?page={$page}&count=10"),
|
||||
function ($response) use ($listId) {
|
||||
throw_unless($response->ok(), MailmanServiceException::class, 'Fetching members for listId '.$listId.' failed.');
|
||||
/** @var array<int, array{email: string}>|null */
|
||||
$entries = data_get($response->json(), 'entries');
|
||||
fn ($page) => $this->http()->get("/lists/{$list->listId}/roster/member?page={$page}&count=10"),
|
||||
function ($response) use ($list) {
|
||||
throw_unless($response->ok(), MailmanServiceException::class, 'Fetching members for listId '.$list->listId.' failed.');
|
||||
/** @var array<int, array{email: string, self_link: string}>|null */
|
||||
$entries = data_get($response->json(), 'entries', []);
|
||||
throw_if(is_null($entries), MailmanServiceException::class, 'Failed getting member list from response');
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
yield $entry['email'];
|
||||
yield Member::from([
|
||||
...$entry,
|
||||
'member_id' => strrev(preg_split('/\//', strrev($entry['self_link']))[0]),
|
||||
]);
|
||||
}
|
||||
},
|
||||
fn ($response) => data_get($response->json(), 'total_size')
|
||||
);
|
||||
}
|
||||
|
||||
public function addMember(MailingList $list, string $email): void
|
||||
{
|
||||
$response = $this->http()->post('members', [
|
||||
'list_id' => $list->listId,
|
||||
'subscriber' => $email,
|
||||
'pre_verified' => 'true',
|
||||
'pre_approved' => 'true',
|
||||
'send_welcome_message' => 'false',
|
||||
'pre_confirmed' => 'true',
|
||||
]);
|
||||
|
||||
throw_unless(201 === $response->status(), MailmanServiceException::class, 'Adding member '.$email.' to '.$list->listId.' failed');
|
||||
}
|
||||
|
||||
public function removeMember(Member $member): void
|
||||
{
|
||||
$response = $this->http()->delete("members/{$member->memberId}");
|
||||
|
||||
throw_unless($response->ok(), MailmanServiceException::class, 'Removing member failed');
|
||||
}
|
||||
|
||||
private function http(): PendingRequest
|
||||
{
|
||||
return Http::withBasicAuth($this->username, $this->password)->withOptions(['base_uri' => $this->baseUrl]);
|
||||
|
|
Loading…
Reference in New Issue