Add member management for mailman
This commit is contained in:
parent
a74d0936a2
commit
904ec829c1
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Mailgateway\Types;
|
namespace App\Mailgateway\Types;
|
||||||
|
|
||||||
use App\Maildispatcher\Data\MailEntry;
|
use App\Maildispatcher\Data\MailEntry;
|
||||||
|
use App\Mailman\Exceptions\MailmanServiceException;
|
||||||
use App\Mailman\Support\MailmanService;
|
use App\Mailman\Support\MailmanService;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ class MailmanType extends Type
|
||||||
|
|
||||||
public function works(): bool
|
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
|
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
|
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
|
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
|
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;
|
namespace App\Mailman\Support;
|
||||||
|
|
||||||
use App\Mailman\Data\MailingList;
|
use App\Mailman\Data\MailingList;
|
||||||
|
use App\Mailman\Data\Member;
|
||||||
use App\Mailman\Exceptions\MailmanServiceException;
|
use App\Mailman\Exceptions\MailmanServiceException;
|
||||||
use App\Mailman\MailmanSettings;
|
use App\Mailman\MailmanSettings;
|
||||||
use Illuminate\Http\Client\ConnectionException;
|
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(
|
return app(Paginator::class)->result(
|
||||||
fn ($page) => $this->http()->get("/lists/{$listId}/roster/member?page={$page}&count=10"),
|
fn ($page) => $this->http()->get("/lists/{$list->listId}/roster/member?page={$page}&count=10"),
|
||||||
function ($response) use ($listId) {
|
function ($response) use ($list) {
|
||||||
throw_unless($response->ok(), MailmanServiceException::class, 'Fetching members for listId '.$listId.' failed.');
|
throw_unless($response->ok(), MailmanServiceException::class, 'Fetching members for listId '.$list->listId.' failed.');
|
||||||
/** @var array<int, array{email: string}>|null */
|
/** @var array<int, array{email: string, self_link: string}>|null */
|
||||||
$entries = data_get($response->json(), 'entries');
|
$entries = data_get($response->json(), 'entries', []);
|
||||||
throw_if(is_null($entries), MailmanServiceException::class, 'Failed getting member list from response');
|
throw_if(is_null($entries), MailmanServiceException::class, 'Failed getting member list from response');
|
||||||
|
|
||||||
foreach ($entries as $entry) {
|
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')
|
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
|
private function http(): PendingRequest
|
||||||
{
|
{
|
||||||
return Http::withBasicAuth($this->username, $this->password)->withOptions(['base_uri' => $this->baseUrl]);
|
return Http::withBasicAuth($this->username, $this->password)->withOptions(['base_uri' => $this->baseUrl]);
|
||||||
|
|
Loading…
Reference in New Issue