feat: send test mail (#7968)

# Which Problems Are Solved

- Zitadel doesn't have a way to test SMTP settings either before
creating a new provider or once the SMTP provider has been created.
- Zitadel SMTP messages can be more informative for usual errors

# How the Problems Are Solved

- A new step is added to the new/update SMTP provider wizard that allows
us to test a configuration. The result is shown in a text area.
- From the table of SMTP providers you can test your settings too.
- The email address to send the email is by default the email address
for the logged in user as suggested.
- Some of the SMTP error messages have been changed to give more
information about the possible situation. For example: could not contact
with the SMTP server, check the port, firewall issues... instead of
could not dial

Here's a video showing this new option in action:


https://github.com/zitadel/zitadel/assets/30386061/50128ba1-c9fa-4481-8eec-e79a3ca69bda

# Additional Changes

Replace this example text with a concise list of additional changes that
this PR introduces, that are not directly solving the initial problem
but are related.
For example:
- The docs explicitly describe that the property XY is mandatory
- Adds missing translations for validations.

# Additional Context

- Closes #4504
This commit is contained in:
Miguel Cabrerizo 2024-06-20 21:51:42 +02:00 committed by GitHub
parent 00b5e55565
commit 3635320ce8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 1362 additions and 46 deletions

View File

@ -2,7 +2,7 @@
title="{{
id ? ('SMTP.DETAIL.TITLE' | translate) : ('SMTP.CREATE.STEPS.TITLE' | translate: { value: providerDefaultSetting.name })
}}"
[createSteps]="3"
[createSteps]="4"
[currentCreateStep]="currentCreateStep"
(closed)="close()"
>
@ -93,7 +93,7 @@
[disabled]="firstFormGroup.invalid"
color="primary"
matStepperNext
data-e2e="continue-button"
data-e2e="continue-to-2nd-form"
>
{{ 'ACTIONS.CONTINUE' | translate }}
</button>
@ -130,19 +130,74 @@
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
<button
mat-raised-button
class="create-button"
[disabled]="secondFormGroup.invalid"
color="primary"
data-e2e="create-button"
(click)="savePolicy(stepper)"
[disabled]="
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
"
matStepperNext
data-e2e="continue-button"
>
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
{{ 'ACTIONS.CONTINUE' | translate }}
</button>
</div>
</mat-step>
<mat-step [editable]="true">
<form>
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.SAVE_SETTINGS' | translate }}</ng-template>
<cnsl-info-section>
<div class="title-row">
<div class="left">
<h2 class="title">{{ 'SMTP.CREATE.STEPS.TEST.TITLE' | translate }}</h2>
</div>
<div class="right">
<button color="primary" mat-raised-button class="continue-button" (click)="testEmailConfiguration()">
{{ 'ACTIONS.TEST' | translate }}
</button>
</div>
</div>
<p class="cnsl-secondary-text description">{{ 'SMTP.CREATE.STEPS.TEST.DESCRIPTION' | translate }}</p>
<cnsl-form-field class="formfield">
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_EMAIL' | translate }}</cnsl-label>
<input
cnslInput
[(ngModel)]="email"
[ngModelOptions]="{ standalone: true }"
data-e2e="email-test-dialog-input"
/>
</cnsl-form-field>
<div class="is-loading" *ngIf="isLoading()">
<mat-spinner diameter="50"></mat-spinner>
</div>
<cnsl-form-field class="formfield" *ngIf="testResult">
<cnsl-label>{{ 'SMTP.LIST.DIALOG.TEST_RESULT' | translate }}</cnsl-label>
<textarea
cnslInput
class="{{ resultClass }}"
[(ngModel)]="testResult"
[ngModelOptions]="{ standalone: true }"
></textarea>
</cnsl-form-field>
</cnsl-info-section>
<div class="smtp-create-actions">
<button mat-stroked-button matStepperPrevious class="bck-button">{{ 'ACTIONS.BACK' | translate }}</button>
<button
mat-raised-button
class="create-button"
color="primary"
data-e2e="create-button"
(click)="savePolicy(stepper)"
[disabled]="
firstFormGroup.invalid || secondFormGroup.invalid || (['iam.policy.write'] | hasRole | async) === false
"
>
{{ !hasSMTPConfig ? ('ACTIONS.CREATE' | translate) : ('ACTIONS.SAVE' | translate) }}
</button>
</div>
</form>
</mat-step>
<mat-step [editable]="true">
<form>
<ng-template matStepLabel>{{ 'SMTP.CREATE.STEPS.NEXT_STEPS' | translate }}</ng-template>

View File

@ -1,8 +1,8 @@
import { COMMA, ENTER, SPACE } from '@angular/cdk/keycodes';
import { Location } from '@angular/common';
import { Component } from '@angular/core';
import { Component, signal } from '@angular/core';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { Subject, take } from 'rxjs';
import { StepperSelectionEvent } from '@angular/cdk/stepper';
import { Options } from 'src/app/proto/generated/zitadel/idp_pb';
import { requiredValidator } from '../form-field/validators/validators';
@ -11,6 +11,7 @@ import { PolicyComponentServiceType } from '../policies/policy-component-types.e
import {
AddSMTPConfigRequest,
AddSMTPConfigResponse,
TestSMTPConfigRequest,
UpdateSMTPConfigRequest,
UpdateSMTPConfigResponse,
} from 'src/app/proto/generated/zitadel/admin_pb';
@ -31,8 +32,10 @@ import {
OutlookDefaultSettings,
SendgridDefaultSettings,
} from './known-smtp-providers-settings';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { MatStepper } from '@angular/material/stepper';
import { SMTPConfigState } from 'src/app/proto/generated/zitadel/settings_pb';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'cnsl-smtp-provider',
@ -61,6 +64,11 @@ export class SMTPProviderComponent {
public senderEmailPlaceholder = 'sender@example.com';
public resultClass = 'test-success';
public isLoading = signal(false);
public email: string = '';
public testResult: string = '';
constructor(
private service: AdminService,
private _location: Location,
@ -68,6 +76,8 @@ export class SMTPProviderComponent {
private toast: ToastService,
private router: Router,
private route: ActivatedRoute,
private authService: GrpcAuthService,
private translate: TranslateService,
) {
this.route.parent?.url.subscribe((urlPath) => {
const providerName = urlPath[urlPath.length - 1].path;
@ -136,6 +146,17 @@ export class SMTPProviderComponent {
this.fetchData(this.id);
}
}
this.authService
.getMyUser()
.then((resp) => {
if (resp.user) {
this.email = resp.user.human?.email?.email || '';
}
})
.catch((error) => {
this.toast.showError(error);
});
});
}
@ -281,6 +302,38 @@ export class SMTPProviderComponent {
});
}
public testEmailConfiguration(): void {
this.isLoading.set(true);
const req = new TestSMTPConfigRequest();
req.setSenderAddress(this.senderAddress?.value ?? '');
req.setSenderName(this.senderName?.value ?? '');
req.setHost(this.hostAndPort?.value ?? '');
req.setUser(this.user?.value);
req.setPassword(this.password?.value ?? '');
req.setTls(this.tls?.value ?? false);
req.setId(this.id ?? '');
req.setReceiverAddress(this.email ?? '');
this.service
.testSMTPConfig(req)
.then(() => {
this.resultClass = 'test-success';
this.isLoading.set(false);
this.translate
.get('SMTP.CREATE.STEPS.TEST.RESULT')
.pipe(take(1))
.subscribe((msg) => {
this.testResult = msg;
});
})
.catch((error) => {
this.resultClass = 'test-error';
this.isLoading.set(false);
this.testResult = error;
});
}
public get description(): AbstractControl | null {
return this.firstFormGroup.get('description');
}

View File

@ -96,4 +96,26 @@
width: 1.2rem;
}
}
.continue-button {
margin-top: 3rem;
display: block;
height: 3.5rem;
padding: 0 4rem;
}
.is-loading {
display: flex;
justify-content: center;
}
.test-error {
border-color: #ff3b5b !important;
min-height: 200px;
}
.test-success {
border-color: #10b981 !important;
min-height: 200px;
}
}

View File

@ -93,6 +93,18 @@
<i class="las la-times-circle"></i>
</button>
<button
actions
[disabled]="(['iam.write'] | hasRole | async) === false"
mat-icon-button
color="primary"
matTooltip="{{ 'SMTP.LIST.TEST' | translate }}"
data-e2e="test-provider-button"
(click)="testSMTPConfig(config.id); $event.stopPropagation()"
>
<i class="las la-flask"></i>
</button>
<button
actions
[disabled]="(['iam.write'] | hasRole | async) === false"

View File

@ -16,6 +16,7 @@ import { SMTPConfig } from 'src/app/proto/generated/zitadel/settings_pb';
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
import { MatTableDataSource } from '@angular/material/table';
import { MatDialog } from '@angular/material/dialog';
import { SmtpTestDialogComponent } from '../smtp-test-dialog/smtp-test-dialog.component';
@Component({
selector: 'cnsl-smtp-table',
@ -149,6 +150,21 @@ export class SMTPTableComponent implements OnInit {
});
}
public testSMTPConfig(id: string): void {
this.dialog.open(SmtpTestDialogComponent, {
data: {
id: id,
confirmKey: 'ACTIONS.TEST',
cancelKey: 'ACTIONS.CLOSE',
titleKey: 'SMTP.LIST.DIALOG.TEST_TITLE',
descriptionKey: 'SMTP.LIST.DIALOG.TEST_DESCRIPTION',
emailKey: 'SMTP.LIST.DIALOG.TEST_EMAIL',
testResultKey: 'SMTP.LIST.DIALOG.TEST_RESULT',
},
width: '500px',
});
}
private async getData(limit: number, offset: number): Promise<void> {
this.loadingSubject.next(true);

View File

@ -18,6 +18,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTableModule } from '@angular/material/table';
import { SmtpTestDialogModule } from '../smtp-test-dialog/smtp-test-dialog.module';
@NgModule({
declarations: [SMTPTableComponent],
@ -40,6 +41,7 @@ import { MatTableModule } from '@angular/material/table';
HasRoleModule,
HasRolePipeModule,
TruncatePipeModule,
SmtpTestDialogModule,
],
exports: [SMTPTableComponent],
})

View File

@ -0,0 +1,47 @@
<h1 mat-dialog-title>
<span>{{ data.titleKey | translate: data.titleParam }}</span>
</h1>
<div mat-dialog-content>
<div class="icon-wrapper" *ngIf="data.icon">
<i class="icon {{ data.icon }}"></i>
</div>
<p class="desc cnsl-secondary-text">{{ data.descriptionKey | translate: data.descriptionParam }}</p>
<cnsl-info-section *ngIf="data.warnSectionKey" [type]="InfoSectionType.WARN">
{{ data.warnSectionKey | translate }}
</cnsl-info-section>
<p *ngIf="data.hintKey" class="desc cnsl-secondary-text">{{ data.hintKey | translate: { value: data.confirmation } }}</p>
<cnsl-form-field class="formfield">
<cnsl-label>{{ data.emailKey | translate }}</cnsl-label>
<input cnslInput [(ngModel)]="email" data-e2e="email-test-dialog-input" />
</cnsl-form-field>
<div class="is-loading" *ngIf="isLoading()">
<mat-spinner diameter="50"></mat-spinner>
</div>
<cnsl-form-field class="formfield" *ngIf="testResult">
<cnsl-label>{{ data.testResultKey | translate }}</cnsl-label>
<textarea cnslInput class="{{ resultClass }}" [(ngModel)]="testResult"></textarea>
</cnsl-form-field>
</div>
<div class="action" mat-dialog-actions>
<button *ngIf="data.cancelKey" mat-stroked-button (click)="closeDialog()">
{{ data.cancelKey | translate }}
</button>
<span class="fill-space"></span>
<button
color="primary"
[disabled]="!email || isLoading()"
mat-raised-button
class="ok-button"
(click)="testEmailConfiguration()"
data-e2e="test-email-button"
>
{{ data.confirmKey | translate }}
</button>
</div>

View File

@ -0,0 +1,51 @@
h1 {
font-size: 1.5rem;
margin: 0;
}
.icon-wrapper {
display: flex;
justify-content: center;
padding: 1rem;
margin: 1rem;
align-items: center;
.icon {
font-size: 3rem;
}
}
.desc {
font-size: 0.9rem;
}
.action {
display: flex;
button {
border-radius: 0.5rem;
}
.ok-button {
margin-left: 0.5rem;
}
.fill-space {
flex: 1;
}
}
.is-loading {
display: flex;
justify-content: center;
}
.test-error {
border-color: #ff3b5b;
min-height: 200px;
}
.test-success {
border-color: #10b981;
min-height: 200px;
}

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
describe('SmtpTestDialogComponent', () => {
let component: SmtpTestDialogComponent;
let fixture: ComponentFixture<SmtpTestDialogComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [SmtpTestDialogComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SmtpTestDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,72 @@
import { Component, Inject, signal } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { InfoSectionType } from '../info-section/info-section.component';
import { AdminService } from 'src/app/services/admin.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ToastService } from 'src/app/services/toast.service';
import { TranslateService } from '@ngx-translate/core';
import { TestSMTPConfigByIdRequest } from 'src/app/proto/generated/zitadel/admin_pb';
import { take } from 'rxjs';
@Component({
selector: 'cnsl-smtp-test-dialog',
templateUrl: './smtp-test-dialog.component.html',
styleUrls: ['./smtp-test-dialog.component.scss'],
})
export class SmtpTestDialogComponent {
public resultClass = 'test-success';
public isLoading = signal(false);
public email: string = '';
public testResult: string = '';
InfoSectionType: any = InfoSectionType;
constructor(
public dialogRef: MatDialogRef<SmtpTestDialogComponent>,
private adminService: AdminService,
private authService: GrpcAuthService,
private toast: ToastService,
private translate: TranslateService,
@Inject(MAT_DIALOG_DATA) public data: any,
) {
this.authService
.getMyUser()
.then((resp) => {
if (resp.user) {
this.email = resp.user.human?.email?.email || '';
}
})
.catch((error) => {
this.toast.showError(error);
});
}
public testEmailConfiguration(): void {
this.isLoading.set(true);
const req = new TestSMTPConfigByIdRequest();
req.setId(this.data.id);
req.setReceiverAddress(this.email);
this.adminService
.testSMTPConfigById(req)
.then(() => {
this.resultClass = 'test-success';
this.isLoading.set(false);
this.translate
.get('SMTP.CREATE.STEPS.TEST.RESULT')
.pipe(take(1))
.subscribe((msg) => {
this.testResult = msg;
});
})
.catch((error) => {
this.resultClass = 'test-error';
this.isLoading.set(false);
this.testResult = error;
});
}
public closeDialog(): void {
this.dialogRef.close(false);
}
}

View File

@ -0,0 +1,26 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { TranslateModule } from '@ngx-translate/core';
import { MatDialogModule } from '@angular/material/dialog';
import { InfoSectionModule } from '../info-section/info-section.module';
import { InputModule } from '../input/input.module';
import { SmtpTestDialogComponent } from './smtp-test-dialog.component';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@NgModule({
declarations: [SmtpTestDialogComponent],
imports: [
CommonModule,
FormsModule,
MatDialogModule,
MatProgressSpinnerModule,
TranslateModule,
InfoSectionModule,
MatButtonModule,
InputModule,
],
})
export class SmtpTestDialogModule {}

View File

@ -240,6 +240,10 @@ import {
SetSecurityPolicyResponse,
SetUpOrgRequest,
SetUpOrgResponse,
TestSMTPConfigByIdRequest,
TestSMTPConfigByIdResponse,
TestSMTPConfigRequest,
TestSMTPConfigResponse,
UpdateAppleProviderRequest,
UpdateAppleProviderResponse,
UpdateAzureADProviderRequest,
@ -330,6 +334,7 @@ import {
} from '../proto/generated/zitadel/milestone/v1/milestone_pb';
import { OrgFieldName, OrgQuery } from '../proto/generated/zitadel/org_pb';
import { SortDirection } from '@angular/material/sort';
import { SMTPConfig } from '../proto/generated/zitadel/settings_pb';
export interface OnboardingActions {
order: number;
@ -946,6 +951,14 @@ export class AdminService {
return this.grpcService.admin.deactivateSMTPConfig(req, null).then((resp) => resp.toObject());
}
public testSMTPConfigById(req: TestSMTPConfigByIdRequest): Promise<TestSMTPConfigByIdResponse.AsObject> {
return this.grpcService.admin.testSMTPConfigById(req, null).then((resp) => resp.toObject());
}
public testSMTPConfig(req: TestSMTPConfigRequest): Promise<TestSMTPConfigResponse.AsObject> {
return this.grpcService.admin.testSMTPConfig(req, null).then((resp) => resp.toObject());
}
public removeSMTPConfig(id: string): Promise<RemoveSMTPConfigResponse.AsObject> {
const req = new RemoveSMTPConfigRequest();
req.setId(id);

View File

@ -485,8 +485,15 @@
"NEXT": "Следващ",
"MORE": "Повече ▼",
"STEP": "стъпка",
"SETUP": "Настройвам",
"COMINGSOON": "Очаквайте скоро",
"TEST": "Тест",
"UNSAVEDCHANGES": "Незапазени промени",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Сигурни ли сте, че искате да отхвърлите това ново действие? Вашето действие ще бъде загубено",
"CANCEL": "Отказ",
"DISCARD": "Изхвърлете"
}
},
"TABLE": {
"SHOWUSER": "Покажи потребител {{value}}"
},
@ -2228,6 +2235,7 @@
"ACTIVATED": "Активиран",
"ACTIVATE": "Активирайте доставчика",
"DEACTIVATE": "Деактивирайте доставчика",
"TEST": "Тествайте вашия доставчик",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "SMTP конфигурацията е активирана",
@ -2251,7 +2259,6 @@
"CURRENT_DESC_TITLE": "Това са вашите SMTP настройки",
"PROVIDER_SETTINGS": "Настройки на SMTP доставчик",
"SENDER_SETTINGS": "Настройки на изпращача",
"TEST_SETTINGS": "Тествайте настройките на SMTP",
"NEXT_STEPS": "Следващи стъпки",
"ACTIVATE": {
"TITLE": "Активирайте вашия SMTP доставчик",
@ -2260,6 +2267,12 @@
"DEACTIVATE": {
"TITLE": "Деактивирайте вашия SMTP доставчик",
"DESCRIPTION": "Ако деактивирате този SMTP доставчик, ZITADEL не може да го използва за изпращане на известия, докато не го активирате отново."
},
"SAVE_SETTINGS": "Запазете вашите настройки",
"TEST": {
"TITLE": "Тествайте настройките си",
"DESCRIPTION": "Можете да тествате настройките на вашия SMTP доставчик и да проверите резултата от теста, преди да ги запазите",
"RESULT": "Вашият имейл беше изпратен успешно"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "více",
"STEP": "Krok",
"SETUP": "Nastavit",
"TEST": "Test",
"UNSAVEDCHANGES": "Neuložené změny",
"UNSAVED": {
"DIALOG": {
@ -2247,6 +2248,7 @@
"ACTIVATED": "Aktivováno",
"ACTIVATE": "Aktivujte poskytovatele",
"DEACTIVATE": "Deaktivovat poskytovatele",
"TEST": "Otestujte svého poskytovatele",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Konfigurace SMTP byla aktivována",
@ -2270,7 +2272,6 @@
"CURRENT_DESC_TITLE": "Toto jsou vaše nastavení SMTP",
"PROVIDER_SETTINGS": "Nastavení poskytovatele SMTP",
"SENDER_SETTINGS": "Nastavení odesílatele",
"TEST_SETTINGS": "Otestujte nastavení SMTP",
"NEXT_STEPS": "Další kroky",
"ACTIVATE": {
"TITLE": "Aktivujte svého poskytovatele SMTP",
@ -2279,6 +2280,12 @@
"DEACTIVATE": {
"TITLE": "Deaktivujte svého poskytovatele SMTP",
"DESCRIPTION": "Pokud deaktivujete tohoto poskytovatele SMTP, ZITADEL jej nebude moci používat k odesílání upozornění, dokud jej znovu neaktivujete."
},
"SAVE_SETTINGS": "Uložte nastavení",
"TEST": {
"TITLE": "Otestujte svá nastavení",
"DESCRIPTION": "Nastavení poskytovatele SMTP můžete otestovat a před uložením zkontrolovat výsledek testu",
"RESULT": "Váš email byl úspěšně odeslán"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Weiter",
"MORE": "mehr",
"STEP": "Schritt",
"SETUP": "Aufstellen",
"TEST": "Prüfen",
"UNSAVEDCHANGES": "Nicht gespeicherte Änderungen",
"UNSAVED": {
"DIALOG": {
@ -2237,6 +2239,7 @@
"ACTIVATED": "Aktiviert",
"ACTIVATE": "Anbieter aktivieren",
"DEACTIVATE": "Anbieter deaktivieren",
"TEST": "Testen Sie Ihren Anbieter",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Die SMTP-Konfiguration wurde aktiviert",
@ -2260,7 +2263,6 @@
"CURRENT_DESC_TITLE": "Dies sind Ihre SMTP-Einstellungen",
"PROVIDER_SETTINGS": "SMTP-Anbietereinstellungen",
"SENDER_SETTINGS": "Absendereinstellungen",
"TEST_SETTINGS": "Testen Sie die SMTP-Einstellungen",
"NEXT_STEPS": "Nächste Schritte",
"ACTIVATE": {
"TITLE": "Aktivieren Sie Ihren SMTP-Anbieter",
@ -2269,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "Deaktivieren Sie Ihren SMTP-Anbieter",
"DESCRIPTION": "Wenn Sie diesen SMTP-Anbieter deaktivieren, kann ZITADEL ihn nicht zum Versenden von Benachrichtigungen verwenden, bis Sie ihn erneut aktivieren."
},
"SAVE_SETTINGS": "Speichern Sie Ihre Einstellungen",
"TEST": {
"TITLE": "Testen Sie Ihre Einstellungen",
"DESCRIPTION": "Sie können die Einstellungen Ihres SMTP-Anbieters testen und das Testergebnis überprüfen, bevor Sie sie speichern",
"RESULT": "Deine E-Mail wurde erfolgreich versandt"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "more",
"STEP": "Step",
"SETUP": "Setup",
"TEST": "Test",
"UNSAVEDCHANGES": "Unsaved changes",
"UNSAVED": {
"DIALOG": {
@ -2259,6 +2260,7 @@
"ACTIVATED": "Activated",
"ACTIVATE": "Activate provider",
"DEACTIVATE": "Deactivate provider",
"TEST": "Test your provider",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "SMTP config has been activated",
@ -2270,7 +2272,11 @@
"DELETE_TITLE": "Delete SMTP config",
"DELETE_DESCRIPTION": "You are about to delete a configuration. Confirm this action typing the sender name",
"DELETED": "SMTP config has been deleted",
"SENDER": "Type {{value}}, to delete this SMTP configuration."
"SENDER": "Type {{value}}, to delete this SMTP configuration.",
"TEST_TITLE": "Test your SMTP config",
"TEST_DESCRIPTION": "Specify an email address to test your SMTP configuration for this provider",
"TEST_EMAIL": "Email address",
"TEST_RESULT": "Test result"
}
},
"CREATE": {
@ -2282,7 +2288,6 @@
"CURRENT_DESC_TITLE": "These are your SMTP settings",
"PROVIDER_SETTINGS": "SMTP Provider Settings",
"SENDER_SETTINGS": "Sender Settings",
"TEST_SETTINGS": "Test SMTP Settings",
"NEXT_STEPS": "Next Steps",
"ACTIVATE": {
"TITLE": "Activate your SMTP Provider",
@ -2291,6 +2296,12 @@
"DEACTIVATE": {
"TITLE": "Deactivate your SMTP Provider",
"DESCRIPTION": "If you deactivate this SMTP Provider, ZITADEL cannot use it to send notifications until you activate it again."
},
"SAVE_SETTINGS": "Save your settings",
"TEST": {
"TITLE": "Test your settings",
"DESCRIPTION": "You can test your SMTP provider settings and check the test result before saving them",
"RESULT": "Your email was succesfully sent"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "más",
"STEP": "Paso",
"SETUP": "Configurar",
"TEST": "Probar",
"UNSAVEDCHANGES": "Cambios no guardados",
"UNSAVED": {
"DIALOG": {
@ -2235,6 +2236,7 @@
"ACTIVATED": "Activado",
"ACTIVATE": "Activar proveedor",
"DEACTIVATE": "Desactivar proveedor",
"TEST": "Prueba tu proveedor",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "Tu configuración SMTP ha sido activada",
@ -2258,7 +2260,6 @@
"CURRENT_DESC_TITLE": "Estas son tus configuraciones SMTP",
"PROVIDER_SETTINGS": "Configuración del proveedor SMTP",
"SENDER_SETTINGS": "Configuración del remitente",
"TEST_SETTINGS": "Probar la configuración SMTP",
"NEXT_STEPS": "Pŕoximos pasos",
"ACTIVATE": {
"TITLE": "Activa tu proveedor SMTP",
@ -2267,6 +2268,12 @@
"DEACTIVATE": {
"TITLE": "Desactiva tu proveedor SMTP",
"DESCRIPTION": "Si desactivas este proveedor SMTP, ZITADEL no puede utilizarlo para enviar notificationes hasta que lo actives otra vez."
},
"SAVE_SETTINGS": "Guarda tu configuración",
"TEST": {
"TITLE": "Prueba tu configuración",
"DESCRIPTION": "Puedes probar tu configuración SMTP y revisar el resultado de la prueba antes de guardar la configuración",
"RESULT": "Tu email fue enviado con éxito"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Suivant",
"MORE": "Plus",
"STEP": "Étape",
"SETUP": "Installation",
"TEST": "Test",
"UNSAVEDCHANGES": "Modifications non enregistrées",
"UNSAVED": {
"DIALOG": {
@ -2238,6 +2240,7 @@
"ACTIVATED": "Activé",
"ACTIVATE": "Activer le fournisseur",
"DEACTIVATE": "Désactiver le fournisseur",
"TEST": "Testez votre fournisseur",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "La configuration SMTP a été activée",
@ -2261,7 +2264,6 @@
"CURRENT_DESC_TITLE": "Ce sont vos paramètres SMTP",
"PROVIDER_SETTINGS": "Paramètres du fournisseur SMTP",
"SENDER_SETTINGS": "Paramètres de l'expéditeur",
"TEST_SETTINGS": "Tester les paramètres SMTP",
"NEXT_STEPS": "Prochaines étapes",
"ACTIVATE": {
"TITLE": "Activez votre fournisseur SMTP",
@ -2270,6 +2272,12 @@
"DEACTIVATE": {
"TITLE": "Désactivez votre fournisseur SMTP",
"DESCRIPTION": "Si vous désactivez l'option SMTP, vous ne pourrez pas vous connecter à l'application, le dossier sera alors désactivé."
},
"SAVE_SETTINGS": "Enregistrez vos paramètres",
"TEST": {
"TITLE": "Testez vos paramètres",
"DESCRIPTION": "Vous pouvez tester les paramètres de votre fournisseur SMTP et vérifier le résultat du test avant de les enregistrer",
"RESULT": "Votre email a été envoyé avec succès"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "Avanti",
"MORE": "azioni",
"STEP": "Passo",
"SETUP": "Setup",
"TEST": "Test",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Sei sicuro di voler eliminare questa nuova azione? La tua azione andrà persa",
@ -2238,6 +2240,7 @@
"ACTIVATED": "Attivato",
"ACTIVATE": "Attiva fornitore",
"DEACTIVATE": "Disattiva fornitore",
"TEST": "Metti alla prova il tuo fornitore",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "La configurazione SMTP è stata attivata",
@ -2261,7 +2264,6 @@
"CURRENT_DESC_TITLE": "Queste sono le tue impostazioni SMTP",
"PROVIDER_SETTINGS": "Impostazioni del provider SMTP",
"SENDER_SETTINGS": "Impostazioni mittente",
"TEST_SETTINGS": "Testare le impostazioni SMTP",
"NEXT_STEPS": "Prossimi passi",
"ACTIVATE": {
"TITLE": "Attiva il tuo provider SMTP",
@ -2270,6 +2272,12 @@
"DEACTIVATE": {
"TITLE": "Disattiva il tuo provider SMTP",
"DESCRIPTION": "Dopo aver disattivato l'archivio SMTP, la schermata non è disponibile per l'utente, il documento è nuovo e non è attivo."
},
"SAVE_SETTINGS": "Salva le tue impostazioni",
"TEST": {
"TITLE": "Metti alla prova le tue impostazioni",
"DESCRIPTION": "Puoi testare le impostazioni del tuo provider SMTP e controllare il risultato del test prima di salvarle",
"RESULT": "La tua email è stata inviata correttamente"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "さらに",
"STEP": "ステップ",
"SETUP": "セットアップ",
"TEST": "テスト",
"UNSAVEDCHANGES": "未保存の変更",
"UNSAVED": {
"DIALOG": {
@ -2230,6 +2231,7 @@
"ACTIVATED": "アクティブ化された",
"ACTIVATE": "プロバイダーをアクティブ化する",
"DEACTIVATE": "プロバイダーを非アクティブ化する",
"TEST": "プロバイダーをテストする",
"TYPE": "タイプ",
"DIALOG": {
"ACTIVATED": "SMTP設定が有効化されました",
@ -2253,7 +2255,6 @@
"CURRENT_DESC_TITLE": "これらは SMTP 設定です",
"PROVIDER_SETTINGS": "SMTPプロバイダーの設定",
"SENDER_SETTINGS": "送信者の設定",
"TEST_SETTINGS": "SMTP設定をテストする",
"NEXT_STEPS": "次のステップ",
"ACTIVATE": {
"TITLE": "SMTP プロバイダーをアクティブ化する",
@ -2262,6 +2263,12 @@
"DEACTIVATE": {
"TITLE": "SMTPプロバイダーを非アクティブ化します",
"DESCRIPTION": "この SMTP プロバイダーを非アクティブ化すると、再度アクティブ化するまで、Zitadel はそれを使用して通知を送信できなくなります。"
},
"SAVE_SETTINGS": "設定を保存する",
"TEST": {
"TITLE": "設定をテストする",
"DESCRIPTION": "SMTP プロバイダーの設定をテストし、保存する前にテスト結果を確認できます。",
"RESULT": "あなたの電子メールが正常に送信されました"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "повеќе",
"STEP": "Чекор",
"SETUP": "Подесување",
"TEST": "Тест",
"UNSAVEDCHANGES": "Незачувани промени",
"UNSAVED": {
"DIALOG": {
@ -2235,6 +2236,7 @@
"ACTIVATED": "Активиран",
"ACTIVATE": "Активирајте го провајдерот",
"DEACTIVATE": "Деактивирајте го провајдерот",
"TEST": "Тестирајте го вашиот провајдер",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "SMTP конфигурацијата е активирана",
@ -2258,7 +2260,6 @@
"CURRENT_DESC_TITLE": "Ова се вашите поставки за SMTP",
"PROVIDER_SETTINGS": "Поставки на провајдерот SMTP",
"SENDER_SETTINGS": "Поставки на испраќачот",
"TEST_SETTINGS": "Тестирајте ги поставките за SMTP",
"NEXT_STEPS": "Следните чекори",
"ACTIVATE": {
"TITLE": "Активирајте го вашиот SMTP провајдер",
@ -2267,6 +2268,12 @@
"DEACTIVATE": {
"TITLE": "Деактивирајте го вашиот SMTP провајдер",
"DESCRIPTION": "Ако го деактивирате овој SMTP провајдер, ZITADEL не може да го користи за испраќање известувања додека не го активирате повторно."
},
"SAVE_SETTINGS": "Зачувајте ги вашите поставки",
"TEST": {
"TITLE": "Тестирајте ги вашите поставки",
"DESCRIPTION": "Можете да ги тестирате поставките на провајдерот SMTP и да го проверите резултатот од тестот пред да ги зачувате",
"RESULT": "Вашата е-пошта беше успешно испратена"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "meer",
"STEP": "Stap",
"SETUP": "Instellen",
"TEST": "Test",
"UNSAVEDCHANGES": "Niet-opgeslagen wijzigingen",
"UNSAVED": {
"DIALOG": {
@ -2256,6 +2257,7 @@
"ACTIVATED": "Geactiveerd",
"ACTIVATE": "Aanbieder activeren",
"DEACTIVATE": "Aanbieder deactiveren",
"TEST": "Test uw aanbieder",
"TYPE": "Type",
"DIALOG": {
"ACTIVATED": "SMTP-configuratie is geactiveerd",
@ -2279,7 +2281,6 @@
"CURRENT_DESC_TITLE": "Dit zijn uw SMTP-instellingen",
"PROVIDER_SETTINGS": "SMTP-providerinstellingen",
"SENDER_SETTINGS": "Afzenderinstellingen",
"TEST_SETTINGS": "SMTP-instellingen testen",
"NEXT_STEPS": "Volgende stappen",
"ACTIVATE": {
"TITLE": "Activeer uw SMTP-provider",
@ -2288,6 +2289,12 @@
"DEACTIVATE": {
"TITLE": "Deactiveer uw SMTP-provider",
"DESCRIPTION": "Als u deze SMTP-provider deactiveert, kan ZITADEL deze niet gebruiken om meldingen te verzenden totdat u deze opnieuw activeert."
},
"SAVE_SETTINGS": "Sla uw instellingen op",
"TEST": {
"TITLE": "Test uw instellingen",
"DESCRIPTION": "U kunt de instellingen van uw SMTP-provider testen en het testresultaat controleren voordat u deze opslaat",
"RESULT": "Je email is succesvol verzonden"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "więcej",
"STEP": "Krok",
"UNSAVEDCHANGES": "Niezapisane zmiany",
"TEST": "Test",
"UNSAVED": {
"DIALOG": {
"DESCRIPTION": "Czy na pewno chcesz odrzucić to nowe działanie? Twoje działanie zostanie utracone",
@ -2238,6 +2239,7 @@
"ACTIVATED": "Aktywowany",
"ACTIVATE": "Aktywuj dostawcę",
"DEACTIVATE": "Dezaktywuj dostawcę",
"TEST": "Przetestuj swojego dostawcę",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "Konfiguracja SMTP została aktywowana",
@ -2261,7 +2263,6 @@
"CURRENT_DESC_TITLE": "To są Twoje ustawienia SMTP",
"PROVIDER_SETTINGS": "Ustawienia dostawcy SMTP",
"SENDER_SETTINGS": "Ustawienia nadawcy",
"TEST_SETTINGS": "Przetestuj ustawienia SMTP",
"NEXT_STEPS": "Następne kroki",
"ACTIVATE": {
"TITLE": "Aktywuj swojego dostawcę SMTP",
@ -2270,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "Dezaktywuj swojego dostawcę SMTP",
"DESCRIPTION": "Jeśli dezaktywujesz tego dostawcę SMTP, ZITADEL nie będzie mógł go używać do wysyłania powiadomień, dopóki nie aktywujesz go ponownie."
},
"SAVE_SETTINGS": "Zapisz swoje ustawienia",
"TEST": {
"TITLE": "Przetestuj swoje ustawienia",
"DESCRIPTION": "Możesz przetestować ustawienia dostawcy SMTP i sprawdzić wynik testu przed ich zapisaniem",
"RESULT": "Twój email został wysłany"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "mais",
"STEP": "Passo",
"SETUP": "Configuração",
"TEST": "Teste",
"UNSAVEDCHANGES": "Alterações não salvas",
"UNSAVED": {
"DIALOG": {
@ -2233,6 +2234,7 @@
"ACTIVATED": "Ativado",
"ACTIVATE": "Ativar provedor",
"DEACTIVATE": "Desativar provedor",
"TEST": "Teste seu provedor",
"TYPE": "Tipo",
"DIALOG": {
"ACTIVATED": "A configuração SMTP foi ativada",
@ -2256,7 +2258,6 @@
"CURRENT_DESC_TITLE": "Estas são suas configurações de SMTP",
"PROVIDER_SETTINGS": "Configurações do provedor SMTP",
"SENDER_SETTINGS": "Configurações do remetente",
"TEST_SETTINGS": "Testar configurações de SMTP",
"NEXT_STEPS": "Próximos passos",
"ACTIVATE": {
"TITLE": "Ative seu provedor SMTP",
@ -2265,6 +2266,12 @@
"DEACTIVATE": {
"TITLE": "Desative seu provedor SMTP",
"DESCRIPTION": "Se você desativar este provedor SMTP, a ZITADEL não poderá usá-lo para enviar notificações até que você o ative novamente."
},
"SAVE_SETTINGS": "Salve suas configurações",
"TEST": {
"TITLE": "Teste suas configurações",
"DESCRIPTION": "Você pode testar as configurações do seu provedor SMTP e verificar o resultado do teste antes de salvá-las",
"RESULT": "Seu e-mail foi enviado com sucesso"
}
}
},

View File

@ -485,6 +485,7 @@
"MORE": "больше",
"STEP": "Шаг",
"SETUP": "Настроить",
"TEST": "Тест",
"UNSAVEDCHANGES": "Несохраненные изменения",
"UNSAVED": {
"DIALOG": {
@ -2350,6 +2351,7 @@
"ACTIVATED": "Активировано",
"ACTIVATE": "Активировать провайдера",
"DEACTIVATE": "Деактивировать провайдера",
"TEST": "Проверьте своего провайдера",
"TYPE": "Тип",
"DIALOG": {
"ACTIVATED": "Конфигурация SMTP активирована",
@ -2373,7 +2375,6 @@
"CURRENT_DESC_TITLE": "Это ваши настройки SMTP",
"PROVIDER_SETTINGS": "Настройки SMTP-провайдера",
"SENDER_SETTINGS": "Настройки отправителя",
"TEST_SETTINGS": "Проверка настроек SMTP",
"NEXT_STEPS": "Следующие шаги",
"ACTIVATE": {
"TITLE": "Активируйте своего SMTP-провайдера",
@ -2382,6 +2383,12 @@
"DEACTIVATE": {
"TITLE": "Деактивируйте своего SMTP-провайдера",
"DESCRIPTION": "Если вы деактивируете этого поставщика SMTP, ZITADEL не сможет использовать его для отправки уведомлений, пока вы не активируете его снова."
},
"SAVE_SETTINGS": "Сохраните настройки",
"TEST": {
"TITLE": "Проверьте свои настройки",
"DESCRIPTION": "Вы можете проверить настройки своего провайдера SMTP и проверить результаты проверки перед их сохранением.",
"RESULT": "Ваше письмо было успешно отправлено"
}
}
},

View File

@ -486,6 +486,7 @@
"MORE": "mer",
"STEP": "Steg",
"SETUP": "Inställning",
"TEST": "Testa",
"UNSAVEDCHANGES": "Osparade ändringar",
"UNSAVED": {
"DIALOG": {
@ -2259,6 +2260,7 @@
"ACTIVATED": "Aktiverad",
"ACTIVATE": "Aktivera leverantör",
"DEACTIVATE": "Inaktivera leverantör",
"TEST": "Testa din leverantör",
"TYPE": "Typ",
"DIALOG": {
"ACTIVATED": "SMTP-konfigurationen har aktiverats",
@ -2270,7 +2272,11 @@
"DELETE_TITLE": "Radera SMTP-konfiguration",
"DELETE_DESCRIPTION": "Du håller på att radera en konfiguration. Bekräfta denna åtgärd genom att skriva avsändarnamnet",
"DELETED": "SMTP-konfigurationen har raderats",
"SENDER": "Skriv {{value}}, för att radera denna SMTP-konfiguration."
"SENDER": "Skriv {{value}}, för att radera denna SMTP-konfiguration.",
"TEST_TITLE": "Testa din SMTP-konfiguration",
"TEST_DESCRIPTION": "Ange en e-postadress för att testa din SMTP-konfiguration för den här leverantören",
"TEST_EMAIL": "E-postadress",
"TEST_RESULT": "Testresultat"
}
},
"CREATE": {
@ -2282,7 +2288,6 @@
"CURRENT_DESC_TITLE": "Dessa är dina SMTP-inställningar",
"PROVIDER_SETTINGS": "SMTP-leverantörsinställningar",
"SENDER_SETTINGS": "Avsändarinställningar",
"TEST_SETTINGS": "Testa SMTP-inställningar",
"NEXT_STEPS": "Nästa steg",
"ACTIVATE": {
"TITLE": "Aktivera din SMTP-leverantör",
@ -2291,6 +2296,12 @@
"DEACTIVATE": {
"TITLE": "Inaktivera din SMTP-leverantör",
"DESCRIPTION": "Om du inaktiverar denna SMTP-leverantör kan ZITADEL inte använda den för att skicka meddelanden förrän du aktiverar den igen."
},
"SAVE_SETTINGS": "Spara dina inställningar",
"TEST": {
"TITLE": "Testa dina inställningar",
"DESCRIPTION": "Du kan testa inställningarna för din SMTP-leverantör och kontrollera testresultatet innan du sparar dem",
"RESULT": "Ditt e-postmeddelande har skickats"
}
}
},

View File

@ -485,6 +485,8 @@
"NEXT": "下一页",
"MORE": "更多",
"STEP": "步",
"SETUP": "设置",
"TEST": "测试",
"UNSAVEDCHANGES": "未保存的更改",
"UNSAVED": {
"DIALOG": {
@ -2237,6 +2239,7 @@
"ACTIVATED": "活性",
"ACTIVATE": "激活提供商",
"DEACTIVATE": "停用提供商",
"TEST": "测试您的提供商",
"TYPE": "类型",
"DIALOG": {
"ACTIVATED": "SMTP 配置已激活",
@ -2260,7 +2263,6 @@
"CURRENT_DESC_TITLE": "这些是您的 SMTP 设置",
"PROVIDER_SETTINGS": "SMTP 提供商设置",
"SENDER_SETTINGS": "发件人设置",
"TEST_SETTINGS": "测试 SMTP 设置",
"NEXT_STEPS": "下一步",
"ACTIVATE": {
"TITLE": "激活您的 SMTP 提供商",
@ -2269,6 +2271,12 @@
"DEACTIVATE": {
"TITLE": "停用您的 SMTP 提供商",
"DESCRIPTION": "如果您停用此 SMTP 提供程序Zitadel 将无法使用它发送通知,直到您再次激活它。"
},
"SAVE_SETTINGS": "保存您的设置",
"TEST": {
"TITLE": "测试您的设置",
"DESCRIPTION": "您可以测试您的 SMTP 提供商设置并在保存之前检查测试结果",
"RESULT": "您的电子邮件已成功发送"
}
}
},

View File

@ -107,6 +107,14 @@ To configure your custom SMTP please fill the following fields:
<img src="/docs/img/guides/console/smtp.png" alt="SMTP" width="800px" />
While you create/update a SMTP provider you have the chance to test your SMTP configuration
<img src="/docs/img/guides/console/smtp_test.png" alt="SMTP" width="800px" />
In the SMTP providers table you can hover on a provider row to show buttons that allow you to activate/deactivate a provider, test your smtp settings and delete a provider
<img src="/docs/img/guides/console/smtp_table.png" alt="SMTP" width="800px" />
### SMS
No default provider is configured to send some SMS to your users. If you like to validate the phone numbers of your users make sure to add your twilio configuration by adding your Sid, Token and Sender Number.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -26,10 +26,11 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org:587');
cy.get('[formcontrolname="user"]').clear().type('user@example.com');
cy.get('[formcontrolname="password"]').clear().type('password');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[formcontrolname="senderAddress"]').clear().type('sender1@example.com');
cy.get('[formcontrolname="senderName"]').clear().type('Test1');
cy.get('[formcontrolname="replyToAddress"]').clear().type('replyto1@example.com');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -44,12 +45,13 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org:587');
cy.get('[formcontrolname="user"]').should('have.value', 'user@example.com');
cy.get('[formcontrolname="user"]').clear().type('change@example.com');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[formcontrolname="senderAddress"]').should('have.value', 'sender1@example.com');
cy.get('[formcontrolname="senderName"]').should('have.value', 'Test1');
cy.get('[formcontrolname="replyToAddress"]').should('have.value', 'replyto1@example.com');
cy.get('[formcontrolname="senderAddress"]').clear().type('senderchange1@example.com');
cy.get('[formcontrolname="senderName"]').clear().type('Change1');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -77,10 +79,11 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'in-v3.mailjet.com:587');
cy.get('[formcontrolname="user"]').clear().type('user@example.com');
cy.get('[formcontrolname="password"]').clear().type('password');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[formcontrolname="senderAddress"]').clear().type('sender2@example.com');
cy.get('[formcontrolname="senderName"]').clear().type('Test2');
cy.get('[formcontrolname="replyToAddress"]').clear().type('replyto2@example.com');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="close-button"]').click();
@ -140,10 +143,11 @@ describe('instance notifications', () => {
cy.get('[formcontrolname="hostAndPort"]').should('have.value', 'smtp.mailgun.org:587');
cy.get('[formcontrolname="user"]').clear().type('user@example.com');
cy.get('[formcontrolname="password"]').clear().type('password');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[formcontrolname="senderAddress"]').clear().type('sender1@example.com');
cy.get('[formcontrolname="senderName"]').clear().type('Test1');
cy.get('[formcontrolname="replyToAddress"]').clear().type('replyto1@example.com');
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();
cy.get('[data-e2e="activate-button"]').click();
@ -159,6 +163,7 @@ describe('instance notifications', () => {
let rowSelector = `tr:contains('mailgun')`;
cy.visit(smtpPath);
cy.get(rowSelector).click();
cy.get('[data-e2e="continue-to-2nd-form"]').click();
cy.get('[data-e2e="continue-button"]').click();
cy.get('[data-e2e="create-button"]').click();
cy.shouldConfirmSuccess();

View File

@ -5,6 +5,7 @@ import (
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/grpc/object"
"github.com/zitadel/zitadel/internal/notification/channels/smtp"
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
)
@ -128,3 +129,29 @@ func (s *Server) DeactivateSMTPConfig(ctx context.Context, req *admin_pb.Deactiv
Details: object.DomainToAddDetailsPb(result),
}, nil
}
func (s *Server) TestSMTPConfigById(ctx context.Context, req *admin_pb.TestSMTPConfigByIdRequest) (*admin_pb.TestSMTPConfigByIdResponse, error) {
err := s.command.TestSMTPConfigById(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress)
if err != nil {
return nil, err
}
return &admin_pb.TestSMTPConfigByIdResponse{}, nil
}
func (s *Server) TestSMTPConfig(ctx context.Context, req *admin_pb.TestSMTPConfigRequest) (*admin_pb.TestSMTPConfigResponse, error) {
config := smtp.Config{}
config.Tls = req.Tls
config.From = req.SenderAddress
config.FromName = req.SenderName
config.SMTP.Host = req.Host
config.SMTP.User = req.User
config.SMTP.Password = req.Password
err := s.command.TestSMTPConfig(ctx, authz.GetInstance(ctx).InstanceID(), req.Id, req.ReceiverAddress, &config)
if err != nil {
return nil, err
}
return &admin_pb.TestSMTPConfigResponse{}, nil
}

View File

@ -285,6 +285,89 @@ func (c *Commands) RemoveSMTPConfig(ctx context.Context, instanceID, id string)
return writeModelToObjectDetails(&smtpConfigWriteModel.WriteModel), nil
}
func (c *Commands) TestSMTPConfig(ctx context.Context, instanceID, id, email string, config *smtp.Config) error {
password := config.SMTP.Password
if email == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9uy", "Errors.SMTPConfig.TestEmailNotFound")
}
if id == "" && password == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-p9kj", "Errors.SMTPConfig.TestPassword")
}
// If the password is not sent it'd mean that the password hasn't been changed for
// the stored configuration identified by its id so we can try to retrieve it
if id != "" && password == "" {
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
if err != nil {
return err
}
if !smtpConfigWriteModel.State.Exists() {
return zerrors.ThrowNotFound(nil, "SMTP-p9cc", "Errors.SMTPConfig.NotFound")
}
password, err = crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
if err != nil {
return err
}
}
config.SMTP.Password = password
// Try to send an email
err := smtp.TestConfiguration(config, email)
if err != nil {
return err
}
return nil
}
func (c *Commands) TestSMTPConfigById(ctx context.Context, instanceID, id, email string) error {
if id == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-99oki", "Errors.IDMissing")
}
if email == "" {
return zerrors.ThrowInvalidArgument(nil, "SMTP-99yth", "Errors.SMTPConfig.TestEmailNotFound")
}
smtpConfigWriteModel, err := c.getSMTPConfig(ctx, instanceID, id, "")
if err != nil {
return err
}
if !smtpConfigWriteModel.State.Exists() {
return zerrors.ThrowNotFound(nil, "SMTP-99klw", "Errors.SMTPConfig.NotFound")
}
password, err := crypto.DecryptString(smtpConfigWriteModel.Password, c.smtpEncryption)
if err != nil {
return err
}
smtpConfig := &smtp.Config{
Description: smtpConfigWriteModel.Description,
Tls: smtpConfigWriteModel.TLS,
From: smtpConfigWriteModel.SenderAddress,
FromName: smtpConfigWriteModel.SenderName,
SMTP: smtp.SMTP{
Host: smtpConfigWriteModel.Host,
User: smtpConfigWriteModel.User,
Password: password,
},
}
// Try to send an email
err = smtp.TestConfiguration(smtpConfig, email)
if err != nil {
return err
}
return nil
}
func checkSenderAddress(writeModel *IAMSMTPConfigWriteModel) error {
if !writeModel.smtpSenderAddressMatchesInstanceDomain {
return nil

View File

@ -1196,6 +1196,329 @@ func TestCommandSide_RemoveSMTPConfig(t *testing.T) {
}
}
func TestCommandSide_TestSMTPConfig(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
instanceID string
id string
email string
config smtp.Config
}
type res struct {
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "id empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "email empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
instanceID: "INSTANCE",
id: "id",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "if password is empty, smtp id must not",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "",
email: "email",
config: smtp.Config{
From: "test@example,com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "example.com:2525",
},
},
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "password empty and smtp config not found, error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "id",
email: "email",
config: smtp.Config{
From: "test@example,com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "example.com:2525",
},
},
},
res: res{
err: zerrors.IsNotFound,
},
},
{
name: "valid new smtp config, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
email: "email",
config: smtp.Config{
From: "test@example.com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "password",
Host: "mail.smtp2go.com:2525",
},
},
},
res: res{
err: zerrors.IsInternal,
},
},
{
name: "valid smtp config using stored password, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewSMTPConfigAddedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"ID",
"test",
true,
"from",
"name",
"",
"mail.smtp2go.com:2525",
"user",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("password"),
},
),
),
),
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
email: "email",
id: "ID",
config: smtp.Config{
From: "test@example.com",
FromName: "Test",
SMTP: smtp.SMTP{
User: "user",
Password: "",
Host: "mail.smtp2go.com:2525",
},
},
},
res: res{
err: zerrors.IsInternal,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
smtpEncryption: tt.fields.alg,
}
err := r.TestSMTPConfig(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.email, &tt.args.config)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func TestCommandSide_TestSMTPConfigById(t *testing.T) {
type fields struct {
eventstore *eventstore.Eventstore
alg crypto.EncryptionAlgorithm
}
type args struct {
ctx context.Context
instanceID string
id string
email string
}
type res struct {
err func(error) bool
}
tests := []struct {
name string
fields fields
args args
res res
}{
{
name: "id empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "email empty, precondition error",
fields: fields{
eventstore: eventstoreExpect(
t,
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
instanceID: "INSTANCE",
id: "id",
},
res: res{
err: zerrors.IsErrorInvalidArgument,
},
},
{
name: "smtp config not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
),
},
args: args{
ctx: context.Background(),
instanceID: "INSTANCE",
id: "id",
email: "email",
},
res: res{
err: zerrors.IsNotFound,
},
},
{
name: "valid smtp config, wrong auth, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewSMTPConfigAddedEvent(
context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
"ID",
"test",
true,
"from",
"name",
"",
"mail.smtp2go.com:2525",
"user",
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("password"),
},
),
),
),
),
alg: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
id: "ID",
instanceID: "INSTANCE",
email: "test@example.com",
},
res: res{
err: zerrors.IsInternal,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore,
smtpEncryption: tt.fields.alg,
}
err := r.TestSMTPConfigById(tt.args.ctx, tt.args.instanceID, tt.args.id, tt.args.email)
if tt.res.err == nil {
assert.NoError(t, err)
}
if tt.res.err != nil && !tt.res.err(err) {
t.Errorf("got wrong err: %v ", err)
}
})
}
}
func newSMTPConfigChangedEvent(ctx context.Context, id, description string, tls bool, fromAddress, fromName, replyTo, host, user string) *instance.SMTPConfigChangedEvent {
changes := []instance.SMTPConfigChanges{
instance.ChangeSMTPConfigDescription(description),

View File

@ -41,22 +41,22 @@ func (email *Email) HandleMessage(message channels.Message) error {
defer email.smtpClient.Close()
emailMsg, ok := message.(*messages.Email)
if !ok {
return zerrors.ThrowInternal(nil, "EMAIL-s8JLs", "message is not EmailMessage")
return zerrors.ThrowInternal(nil, "EMAIL-s8JLs", "Errors.SMTP.NotEmailMessage")
}
if emailMsg.Content == "" || emailMsg.Subject == "" || len(emailMsg.Recipients) == 0 {
return zerrors.ThrowInternalf(nil, "EMAIL-zGemZ", "subject, recipients and content must be set but got subject %s, recipients length %d and content length %d", emailMsg.Subject, len(emailMsg.Recipients), len(emailMsg.Content))
return zerrors.ThrowInternal(nil, "EMAIL-zGemZ", "Errors.SMTP.RequiredAttributes")
}
emailMsg.SenderEmail = email.senderAddress
emailMsg.SenderName = email.senderName
emailMsg.ReplyToAddress = email.replyToAddress
// To && From
if err := email.smtpClient.Mail(emailMsg.SenderEmail); err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s3is3", "could not set sender: %v", emailMsg.SenderEmail)
return zerrors.ThrowInternal(err, "EMAIL-s3is3", "Errors.SMTP.CouldNotSetSender")
}
for _, recp := range append(append(emailMsg.Recipients, emailMsg.CC...), emailMsg.BCC...) {
if err := email.smtpClient.Rcpt(recp); err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s4is4", "could not set recipient: %v", recp)
return zerrors.ThrowInternal(err, "EMAIL-s4is4", "Errors.SMTP.CouldNotSetRecipient")
}
}
@ -87,7 +87,7 @@ func (email *Email) HandleMessage(message channels.Message) error {
func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err error) {
host, _, err := net.SplitHostPort(smtpConfig.Host)
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-spR56", "could not split host and port for connect to smtp")
return nil, zerrors.ThrowInternal(err, "EMAIL-spR56", "Errors.SMTP.CouldNotSplit")
}
if !tlsRequired {
@ -109,7 +109,7 @@ func (smtpConfig SMTP) connectToSMTP(tlsRequired bool) (client *smtp.Client, err
func (smtpConfig SMTP) getSMTPClient() (*smtp.Client, error) {
client, err := smtp.Dial(smtpConfig.Host)
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-skwos", "could not make smtp dial")
return nil, zerrors.ThrowInternal(err, "EMAIL-skwos", "Errors.SMTP.CouldNotDial")
}
return client, nil
}
@ -118,17 +118,17 @@ func (smtpConfig SMTP) getSMTPClientWithTls(host string) (*smtp.Client, error) {
conn, err := tls.Dial("tcp", smtpConfig.Host, &tls.Config{})
if errors.As(err, &tls.RecordHeaderError{}) {
logging.Log("MAIN-xKIzT").OnError(err).Warn("could not connect using normal tls. trying starttls instead...")
logging.OnError(err).Warn("could not connect using normal tls. trying starttls instead...")
return smtpConfig.getSMTPClientWithStartTls(host)
}
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-sl39s", "could not make tls dial")
return nil, zerrors.ThrowInternal(err, "EMAIL-sl39s", "Errors.SMTP.CouldNotDialTLS")
}
client, err := smtp.NewClient(conn, host)
if err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-skwi4", "could not create smtp client")
return nil, zerrors.ThrowInternal(err, "EMAIL-skwi4", "Errors.SMTP.CouldNotCreateClient")
}
return client, err
}
@ -142,7 +142,7 @@ func (smtpConfig SMTP) getSMTPClientWithStartTls(host string) (*smtp.Client, err
if err := client.StartTLS(&tls.Config{
ServerName: host,
}); err != nil {
return nil, zerrors.ThrowInternal(err, "EMAIL-guvsQ", "could not start tls")
return nil, zerrors.ThrowInternal(err, "EMAIL-guvsQ", "Errors.SMTP.CouldNotStartTLS")
}
return client, nil
}
@ -154,7 +154,56 @@ func (smtpConfig SMTP) smtpAuth(client *smtp.Client, host string) error {
// Auth
err := client.Auth(PlainOrLoginAuth(smtpConfig.User, smtpConfig.Password, host))
if err != nil {
return zerrors.ThrowInternalf(err, "EMAIL-s9kfs", "could not add smtp auth for user %s", smtpConfig.User)
return zerrors.ThrowInternal(err, "EMAIL-s9kfs", "Errors.SMTP.CouldNotAuth")
}
return nil
}
func TestConfiguration(cfg *Config, testEmail string) error {
client, err := cfg.SMTP.connectToSMTP(cfg.Tls)
if err != nil {
return err
}
defer client.Close()
message := &messages.Email{
Recipients: []string{testEmail},
Subject: "Test email",
Content: "This is a test email to check if your SMTP provider works fine",
SenderEmail: cfg.From,
SenderName: cfg.FromName,
}
if err := client.Mail(cfg.From); err != nil {
return zerrors.ThrowInternal(err, "EMAIL-s3is3", "Errors.SMTP.CouldNotSetSender")
}
if err := client.Rcpt(testEmail); err != nil {
return zerrors.ThrowInternal(err, "EMAIL-s4is4", "Errors.SMTP.CouldNotSetRecipient")
}
// Open data connection
w, err := client.Data()
if err != nil {
return err
}
// Send content
content, err := message.GetContent()
if err != nil {
return err
}
_, err = w.Write([]byte(content))
if err != nil {
return err
}
// Close IO and quit smtp connection
err = w.Close()
if err != nil {
return err
}
return client.Quit()
}

View File

@ -53,13 +53,26 @@ Errors:
NotFound: SMS конфигурацията не е намерена
AlreadyActive: SMS конфигурацията вече е активна
AlreadyDeactivated: SMS конфигурацията вече е деактивирана
SMTP:
NotEmailMessage: съобщението не е имейл съобщение
RequiredAttributes: темата, получателите и съдържанието трябва да бъдат зададени, но някои или всички са празни
CouldNotSplit: не можа да раздели хост и порт за свързване към smtp
CouldNotDial: не може да се свърже със SMTP сървъра, проверете порта, проблеми със защитната стена...
CouldNotDialTLS: не може да се свърже със SMTP сървъра чрез TLS, проверете порта, проблеми със защитната стена...
CouldNotCreateClient: не може да създаде smtp клиент
CouldNotStartTLS: не можа да стартира TLS
CouldNotAuth: не може да добави smtp auth, проверете дали потребителят и паролата ви са правилни, ако са правилни, може би вашият доставчик изисква метод за удостоверяване, който не се поддържа от ZITADEL
CouldNotSetSender: не можа да зададе подател
CouldNotSetRecipient: не можа да зададе получател
SMTPConfig:
TestPassword: Паролата за тест не е намерена
NotFound: SMTP конфигурацията не е намерена
AlreadyExists: SMTP конфигурация вече съществува
AlreadyDeactivated: SMTP конфигурацията вече е деактивирана
SenderAdressNotCustomDomain: >-
Адресът на изпращача трябва да бъде конфигуриран като персонализиран
домейн в екземпляра.
TestEmailNotFound: Имейл адресът за теста не е намерен
Notification:
NoDomain: Няма намерен домейн за съобщение
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Konfigurace SMS nebyla nalezena
AlreadyActive: Konfigurace SMS je již aktivní
AlreadyDeactivated: Konfigurace SMS je již deaktivovaná
SMTP:
NotEmailMessage: zpráva není EmailMessage
RequiredAttributes: předmět, příjemci a obsah musí být nastaveny, ale některé nebo všechny jsou prázdné
CouldNotSplit: nemohl rozdělit hostitele a port pro připojení k smtp
CouldNotDial: nelze se spojit se serverem SMTP, zkontrolovat port, problémy s firewallem...
CouldNotDialTLS: nelze se spojit se serverem SMTP pomocí TLS, zkontrolovat port, problémy s firewallem...
CouldNotCreateClient: nelze vytvořit smtp klienta
CouldNotStartTLS: nelze spustit tls
CouldNotAuth: nemohlo se přidat smtp auth, zkontrolujte, zda je váš uživatel i heslo správné, pokud jsou správné, možná váš poskytovatel vyžaduje metodu auth, kterou ZITADEL nepodporuje
CouldNotSetSender: nelze nastavit odesílatele
CouldNotSetRecipient: nelze nastavit příjemce
SMTPConfig:
TestPassword: Heslo pro test nenalezeno
NotFound: Konfigurace SMTP nebyla nalezena
AlreadyExists: Konfigurace SMTP již existuje
AlreadyDeactivated: Konfigurace SMTP je již deaktivována
SenderAdressNotCustomDomain: Adresa odesílatele musí být nakonfigurována jako vlastní doména na instanci.
TestEmailNotFound: E-mailová adresa pro test nebyla nalezena
Notification:
NoDomain: Pro zprávu nebyla nalezena žádná doména
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS Konfiguration nicht gefunden
AlreadyActive: SMS Konfiguration ist bereits aktiviert
AlreadyDeactivated: SMS Konfiguration ist bereits deaktiviert
SMTP:
NotEmailMessage: Die Nachricht ist nicht EmailMessage
RequiredAttributes: Betreff, Empfänger und Inhalt müssen festgelegt werden, aber einige oder alle davon sind leer
CouldNotSplit: Host und Port konnten für die Verbindung zu SMTP nicht getrennt werden
CouldNotDial: Es konnte keine Verbindung zum SMTP-Server hergestellt werden, Port überprüfen, Firewall-Probleme ...
CouldNotDialTLS: Es konnte keine Verbindung zum SMTP-Server über TLS hergestellt werden, überprüfen Sie den Port, Firewall-Probleme ...
CouldNotCreateClient: Der SMTP-Client konnte nicht erstellt werden
CouldNotStartTLS: TLS konnte nicht gestartet werden
CouldNotAuth: Die SMTP-Authentifizierung konnte nicht hinzugefügt werden. Überprüfen Sie, ob sowohl Ihr Benutzername als auch Ihr Passwort korrekt sind. Wenn sie korrekt sind, erfordert Ihr Anbieter möglicherweise eine Authentifizierungsmethode, die von ZITADEL nicht unterstützt wird
CouldNotSetSender: Absender konnte nicht eingestellt werden
CouldNotSetRecipient: Der Empfänger konnte nicht festgelegt werden
SMTPConfig:
TestPassword: Passwort für Test nicht gefunden
NotFound: SMTP Konfiguration nicht gefunden
AlreadyExists: SMTP Konfiguration existiert bereits
AlreadyDeactivated: SMTP-Konfiguration bereits deaktiviert
SenderAdressNotCustomDomain: Die Sender Adresse muss als Custom Domain auf der Instanz registriert sein.
TestEmailNotFound: E-Mail-Adresse für den Test nicht gefunden
Notification:
NoDomain: Keine Domäne für Nachricht gefunden
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS configuration not found
AlreadyActive: SMS configuration already active
AlreadyDeactivated: SMS configuration already deactivated
SMTP:
NotEmailMessage: message is not EmailMessage
RequiredAttributes: subject, recipients and content must be set but some or all of them are empty
CouldNotSplit: could not split host and port for connect to smtp
CouldNotDial: could not contact with the SMTP server, check the port, firewall issues...
CouldNotDialTLS: could not contact with the SMTP server using TLS, check the port, firewall issues...
CouldNotCreateClient: could not create smtp client
CouldNotStartTLS: could not start tls
CouldNotAuth: could not add smtp auth, check if both your user and password are correct, if they're correct maybe your provider requires an auth method not supported by ZITADEL
CouldNotSetSender: could not set sender
CouldNotSetRecipient: could not set recipient
SMTPConfig:
TestPassword: Password for test not found
NotFound: SMTP configuration not found
AlreadyExists: SMTP configuration already exists
AlreadyDeactivated: SMTP configuration already deactivated
SenderAdressNotCustomDomain: The sender address must be configured as custom domain on the instance.
TestEmailNotFound: Email address for test not found
Notification:
NoDomain: No Domain found for message
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: configuración SMS no encontrada
AlreadyActive: la configuración SMS ya está activa
AlreadyDeactivated: la configuracion SMS ya está desactivada
SMTP:
NotEmailMessage: el mensaje no es EmailMessage
RequiredAttributes: Se deben configurar el asunto, los destinatarios y el contenido, pero algunos o todos están vacíos.
CouldNotSplit: No se pudo dividir el host y el puerto para conectarse a SMTP
CouldNotDial: No se pudo contactar con el servidor SMTP, verifique el puerto, problemas con el firewall...
CouldNotDialTLS: No se pudo contactar con el servidor SMTP usando TLS, verifique el puerto, problemas con el firewall...
CouldNotCreateClient: no se pudo crear el cliente smtp
CouldNotStartTLS: no se pudo iniciar TLS
CouldNotAuth: no se pudo agregar la autenticación smtp, verifique si tanto su usuario como su contraseña son correctos, si son correctos tal vez su proveedor requiera un método de autenticación no admitido por ZITADEL
CouldNotSetSender: no se pudo configurar el remitente
CouldNotSetRecipient: No se pudo establecer el destinatario
SMTPConfig:
TestPassword: Contraseña para la prueba no encontrada
NotFound: configuración SMTP no encontrada
AlreadyExists: la configuración SMTP ya existe
AlreadyDeactivated: la configuración SMTP ya está desactivada
SenderAdressNotCustomDomain: La dirección del remitente debe configurarse como un dominio personalizado en la instancia.
TestEmailNotFound: Dirección de correo electrónico para la prueba no encontrada
Notification:
NoDomain: No se encontró el dominio para el mensaje
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Configuration SMS non trouvée
AlreadyActive: Configuration SMS déjà active
AlreadyDeactivated: Configuration SMS déjà désactivée
SMTP:
NotEmailMessage: le message n'est pas un EmailMessage
RequiredAttributes: le sujet, les destinataires et le contenu doivent être définis mais certains ou la totalité d'entre eux sont vides
CouldNotSplit: impossible de diviser l'hôte et le port pour la connexion à SMTP
CouldNotDial: impossible de contacter le serveur SMTP, vérifier le port, problèmes de pare-feu...
CouldNotDialTLS: Impossible de contacter le serveur SMTP via TLS, vérifiez le port, problèmes de pare-feu...
CouldNotCreateClient: impossible de créer un client SMTP
CouldNotStartTLS: je n'ai pas pu démarrer tls
CouldNotAuth: Impossible d'ajouter l'authentification SMTP, vérifiez si votre utilisateur et votre mot de passe sont corrects. S'ils sont corrects, votre fournisseur nécessite peut-être une méthode d'authentification non prise en charge par ZITADEL.
CouldNotSetSender: impossible de définir l'expéditeur
CouldNotSetRecipient: impossible de définir le destinataire
SMTPConfig:
TestPassword: Mot de passe pour le test introuvable
NotFound: Configuration SMTP non trouvée
AlreadyExists: La configuration SMTP existe déjà
AlreadyDeactivated: Configuration SMTP déjà désactivée
SenderAdressNotCustomDomain: L'adresse de l'expéditeur doit être configurée comme un domaine personnalisé sur l'instance.
TestEmailNotFound: Adresse e-mail pour le test introuvable
Notification:
NoDomain: Aucun domaine trouvé pour le message
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Configurazione SMS non trovata
AlreadyActive: Configurazione SMS già attiva
AlreadyDeactivated: Configurazione SMS già disattivata
SMTP:
NotEmailMessage: il messaggio non è EmailMessage
RequiredAttributes: oggetto, destinatari e contenuto devono essere impostati ma alcuni o tutti sono vuoti
CouldNotSplit: impossibile dividere l'host e la porta per la connessione a SMTP
CouldNotDial: impossibile contattare il server SMTP, controllare la porta, problemi con il firewall...
CouldNotDialTLS: Impossibile contattare con il server SMTP utilizzando TLS, controllare la porta, problemi di firewall ...
CouldNotCreateClient: impossibile creare il client SMTP
CouldNotStartTLS: impossibile avviare tls
CouldNotAuth: impossibile aggiungere l'autenticazione smtp, controlla se sia l'utente che la password sono corretti, se sono corretti forse il tuo provider richiede un metodo di autenticazione non supportato da ZITADEL
CouldNotSetSender: impossibile impostare il mittente
CouldNotSetRecipient: impossibile impostare il destinatario
SMTPConfig:
TestPassword: Password per il test non trovata
NotFound: Configurazione SMTP non trovata
AlreadyExists: La configurazione SMTP esiste già
AlreadyDeactivated: Configurazione SMTP già disattivata
SenderAdressNotCustomDomain: L'indirizzo del mittente deve essere configurato come dominio personalizzato sull'istanza.
TestEmailNotFound: Indirizzo email per il test non trovato
Notification:
NoDomain: Nessun dominio trovato per il messaggio
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS構成が見つかりません
AlreadyActive: このSMS構成はすでにアクティブです
AlreadyDeactivated: このSMS構成はすでに非アクティブです
SMTP:
NotEmailMessage: メッセージは EmailMessage ではありません
RequiredAttributes: 件名、受信者、コンテンツを設定する必要がありますが、一部またはすべてが空です
CouldNotSplit: smtp に接続するためにホストとポートを分割できませんでした
CouldNotDial: SMTP サーバーに接続できませんでした。ポート、ファイアウォールの問題を確認してください...
CouldNotDialTLS: TLS を使用して SMTP サーバーに接続できませんでした。ポート、ファイアウォールの問題を確認してください...
CouldNotCreateClient: SMTPクライアントを作成できませんでした
CouldNotStartTLS: TLSを開始できませんでした
CouldNotAuth: smtp 認証を追加できませんでした。ユーザーとパスワードの両方が正しいかどうかを確認してください。正しい場合は、プロバイダーが ZITADEL でサポートされていない認証方法を必要としている可能性があります。
CouldNotSetSender: 送信者を設定できませんでした
CouldNotSetRecipient: 受信者を設定できませんでした
SMTPConfig:
TestPassword: テスト用のパスワードが見つかりません
NotFound: SMTP構成が見つかりません
AlreadyExists: すでに存在するSMTP構成です
AlreadyDeactivated: SMTP設定はすでに無効化されています
SenderAdressNotCustomDomain: 送信者アドレスは、インスタンスのカスタムドメインとして構成する必要があります。
TestEmailNotFound: テスト用のメールアドレスが見つかりません
Notification:
NoDomain: メッセージのドメインが見つかりません
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS конфигурацијата не е пронајдена
AlreadyActive: SMS конфигурацијата е веќе активна
AlreadyDeactivated: SMS конфигурацијата е веќе деактивирана
SMTP:
NotEmailMessage: пораката не е Email Message
RequiredAttributes: предметот, примачите и содржината мора да бидат поставени, но некои или сите се празни
CouldNotSplit: не може да се подели домаќинот и портата за поврзување со smtp
CouldNotDial: не можев да контактираме со SMTP-серверот, да ја провериме портата, проблеми со заштитен ѕид...
CouldNotDialTLS: не можев да контактираме со SMTP-серверот користејќи TLS, проверете ја портата, проблеми со заштитен ѕид...
CouldNotCreateClient: не можев да креирам smtp клиент
CouldNotStartTLS: не можеше да започне tls
CouldNotAuth: не можев да додадам smtp auth, проверете дали и корисникот и лозинката се точни, дали се точни, можеби вашиот провајдер бара метод за автетика што не е поддржан од ZITADEL
CouldNotSetSender: не може да се постави испраќач
CouldNotSetRecipient: не може да се постави примач
SMTPConfig:
TestPassword: Лозинката за тестот не е пронајдена
NotFound: SMTP конфигурацијата не е пронајдена
AlreadyExists: SMTP конфигурацијата веќе постои
AlreadyDeactivated: SMTP конфигурацијата е веќе деактивирана
SenderAdressNotCustomDomain: Адресата на испраќачот мора да биде конфигурирана како прилагоден домен на инстанцата.
TestEmailNotFound: Адресата на е-пошта за тест не е пронајдена
Notification:
NoDomain: Не е пронајден домен за пораката
User:

View File

@ -53,10 +53,24 @@ Errors:
NotFound: SMS-configuratie niet gevonden
AlreadyActive: SMS-configuratie al actief
AlreadyDeactivated: SMS-configuratie al gedeactiveerd
SMTP:
NotEmailMessage: bericht is geen E-mailbericht
RequiredAttributes: onderwerp, ontvangers en inhoud moeten worden ingesteld, maar sommige of allemaal zijn leeg
CouldNotSplit: Kan host en poort niet splitsen voor verbinding met smtp
CouldNotDial: Kan geen contact maken met de SMTP-server, controleer de poort, firewallproblemen...
CouldNotDialTLS: kon geen contact maken met de SMTP-server via TLS, controleer de poort, firewallproblemen...
CouldNotCreateClient: kan geen smtp-client maken
CouldNotStartTLS: kon tls niet starten
CouldNotAuth: kon geen smtp-authenticatie toevoegen, controleer of zowel uw gebruiker als uw wachtwoord correct zijn. Als ze correct zijn, vereist uw provider misschien een auth-methode die niet door ZITADEL wordt ondersteund
CouldNotSetSender: kon de afzender niet instellen
CouldNotSetRecipient: Kan de ontvanger niet instellen
SMTPConfig:
TestPassword: Wachtwoord voor test niet gevonden
NotFound: SMTP-configuratie niet gevonden
AlreadyExists: SMTP-configuratie bestaat al
AlreadyDeactivated: SMTP-configuratie al gedeactiveerd
SenderAdressNotCustomDomain: Het afzenderadres moet worden geconfigureerd als aangepaste domein op de instantie.
TestEmailNotFound: E-mailadres voor test niet gevonden
Notification:
NoDomain: Geen domein gevonden voor bericht
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Konfiguracja SMS nie znaleziona
AlreadyActive: Konfiguracja SMS już aktywna
AlreadyDeactivated: Konfiguracja SMS już dezaktywowana
SMTP:
NotEmailMessage: wiadomość nie jest wiadomością e-mail
RequiredAttributes: Temat, odbiorcy i treść muszą być ustawione, ale niektóre lub wszystkie z nich są puste
CouldNotSplit: nie można podzielić hosta i portu w celu połączenia z smtp
CouldNotDial: nie można połączyć się z serwerem SMTP, sprawdzić port, problemy z zaporą sieciową...
CouldNotDialTLS: nie można połączyć się z serwerem SMTP przy użyciu protokołu TLS, sprawdź port, problemy z zaporą sieciową...
CouldNotCreateClient: nie można utworzyć klienta smtp
CouldNotStartTLS: nie można rozpocząć tls
CouldNotAuth: nie można dodać uwierzytelnienia smtp, sprawdź, czy zarówno użytkownik, jak i hasło są poprawne, jeśli są poprawne, być może Twój dostawca wymaga metody uwierzytelniania nieobsługiwanej przez ZITADEL
CouldNotSetSender: nie można ustawić nadawcy
CouldNotSetRecipient: nie można ustawić odbiorcy
SMTPConfig:
TestPassword: Nie znaleziono hasła do testu
NotFound: Konfiguracja SMTP nie znaleziona
AlreadyExists: Konfiguracja SMTP już istnieje
AlreadyDeactivated: Konfiguracja SMTP jest już dezaktywowana
SenderAdressNotCustomDomain: Adres nadawcy musi być skonfigurowany jako domena niestandardowa na instancji.
TestEmailNotFound: Nie znaleziono adresu e-mail do testu
Notification:
NoDomain: Nie znaleziono domeny dla wiadomości
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Configuração de SMS não encontrada
AlreadyActive: Configuração de SMS já está ativa
AlreadyDeactivated: Configuração de SMS já está desativada
SMTP:
NotEmailMessage: a mensagem não é EmailMessage
RequiredAttributes: assunto, destinatários e conteúdo devem ser definidos, mas alguns ou todos eles estão vazios
CouldNotSplit: não foi possível dividir o host e a porta para conectar ao smtp
CouldNotDial: não foi possível entrar em contato com o servidor SMTP, verificar a porta, problemas de firewall...
CouldNotDialTLS: não foi possível entrar em contato com o servidor SMTP usando TLS, verifique a porta, problemas de firewall...
CouldNotCreateClient: não foi possível criar o cliente smtp
CouldNotStartTLS: não foi possível iniciar o tls
CouldNotAuth: não foi possível adicionar autenticação smtp, verifique se seu usuário e senha estão corretos, se estiverem corretos, talvez seu provedor exija um método de autenticação não suportado pelo ZITADEL
CouldNotSetSender: não foi possível definir o remetente
CouldNotSetRecipient: não foi possível definir o destinatário
SMTPConfig:
TestPassword: Senha para teste não encontrada
NotFound: Configuração de SMTP não encontrada
AlreadyExists: Configuração de SMTP já existe
AlreadyDeactivated: Configuração SMTP já desativada
SenderAdressNotCustomDomain: O endereço do remetente deve ser configurado como um domínio personalizado na instância.
TestEmailNotFound: Endereço de e-mail para teste não encontrado
Notification:
NoDomain: Nenhum domínio encontrado para a mensagem
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: Конфигурация SMS не найдена
AlreadyActive: Конфигурация SMS уже активна
AlreadyDeactivated: Конфигурация SMS уже деактивирована
SMTP:
NotEmailMessage: сообщение не является EmailMessage
RequiredAttributes: тема, получатели и контент должны быть заданы, но некоторые или все из них пусты.
CouldNotSplit: не удалось разделить хост и порт для подключения к smtp
CouldNotDial: не удалось связаться с SMTP-сервером, проверить порт, проблемы с брандмауэром...
CouldNotDialTLS: не удалось связаться с SMTP-сервером с помощью TLS, проверьте порт, проблемы с брандмауэром...
CouldNotCreateClient: не удалось создать smtp-клиент
CouldNotStartTLS: не удалось запустить тлс
CouldNotAuth: не удалось добавить аутентификацию smtp, проверьте правильность вашего пользователя и пароля. Если они верны, возможно, ваш провайдер требует метод аутентификации, не поддерживаемый ZITADEL
CouldNotSetSender: не удалось установить отправителя
CouldNotSetRecipient: не удалось установить получателя
SMTPConfig:
TestPassword: Пароль для теста не найден
NotFound: Конфигурация SMTP не найдена
AlreadyExists: Конфигурация SMTP уже существует
AlreadyDeactivated: Конфигурация SMTP уже деактивирована
SenderAdressNotCustomDomain: Адрес отправителя должен быть настроен как личный домен на экземпляре.
TestEmailNotFound: Адрес электронной почты для теста не найден
Notification:
NoDomain: Домен не найден
User:

View File

@ -53,11 +53,24 @@ Errors:
NotFound: SMS-konfiguration hittades inte
AlreadyActive: SMS-konfiguration redan aktiv
AlreadyDeactivated: SMS-konfiguration redan avaktiverad
SMTP:
NotEmailMessage: meddelandet är inte EmailMessage
RequiredAttributes: Ämne, mottagare och innehåll måste anges men några eller alla är tomma
CouldNotSplit: kunde inte dela värd och port för anslutning till smtp
CouldNotDial: kunde inte kontakta SMTP-servern, kontrollera porten, brandväggsproblem...
CouldNotDialTLS: kunde inte kontakta SMTP-servern med TLS, kontrollera porten, brandväggsproblem...
CouldNotCreateClient: kunde inte skapa smtp-klient
CouldNotStartTLS: kunde inte starta tls
CouldNotAuth: kunde inte lägga till smtp auth, kontrollera om både din användare och lösenord är korrekta, om de är korrekta kanske din leverantör kräver en auth-metod som inte stöds av ZITADEL
CouldNotSetSender: kunde inte ställa in avsändare
CouldNotSetRecipient: kunde inte ange mottagare
SMTPConfig:
TestPassword: Lösenordet för testet hittades inte
NotFound: SMTP-konfiguration hittades inte
AlreadyExists: SMTP-konfiguration finns redan
AlreadyDeactivated: SMTP-konfiguration redan avaktiverad
SenderAdressNotCustomDomain: Avsändaradressen måste sättas som kundanpassad domän på instansen.
TestEmailNotFound: E-postadressen för testet hittades inte
Notification:
NoDomain: Ingen domän hittades för meddelandet
User:
@ -1340,4 +1353,3 @@ Action:
PreUserinfoCreation: Före skapande av användarinformation
PreAccessTokenCreation: Före skapande av åtkomsttoken
PreSAMLResponseCreation: Före skapande av SAMLResponse

View File

@ -53,11 +53,24 @@ Errors:
NotFound: 未找到 SMS 配置
AlreadyActive: SMS 配置已启用
AlreadyDeactivated: SMS 配置已停用
SMTP:
NotEmailMessage: 消息不是电子邮件消息
RequiredAttributes: 必须设置主题、收件人和内容,但部分或全部为空
CouldNotSplit: 无法拆分主机和端口以连接到 smtp
CouldNotDial: 无法与 SMTP 服务器联系,请检查端口、防火墙问题...
CouldNotDialTLS: 无法使用 TLS 与 SMTP 服务器联系,请检查端口、防火墙问题...
CouldNotCreateClient: 无法创建 smtp 客户端
CouldNotStartTLS: 无法启动 tls
CouldNotAuth: 无法添加 smtp 身份验证,请检查您的用户名和密码是否正确,如果正确,可能您的提供商需要 ZITADEL 不支持的身份验证方法
CouldNotSetSender: 无法设置发件人
CouldNotSetRecipient: 无法设置收件人
SMTPConfig:
TestPassword: 未找到测试密码
NotFound: 未找到 SMTP 配置
AlreadyExists: SMTP 配置已存在
AlreadyDeactivated: SMTP 配置已停用
SenderAdressNotCustomDomain: 发件人地址必须在在实例的域名设置中验证。
TestEmailNotFound: 找不到用于测试的电子邮件地址
Notification:
NoDomain: 未找到对应的域名
User:

View File

@ -506,6 +506,40 @@ service AdminService {
};
}
rpc TestSMTPConfigById(TestSMTPConfigByIdRequest) returns (TestSMTPConfigByIdResponse) {
option (google.api.http) = {
post: "/smtp/{id}/_test";
body: "*"
};
option (zitadel.v1.auth_option) = {
permission: "iam.write";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "SMTP Provider";
summary: "Test SMTP Provider ";
description: "Test an SMTP provider identified by its ID. After testing the provider, the users will receive information about the test results."
};
}
rpc TestSMTPConfig(TestSMTPConfigRequest) returns (TestSMTPConfigResponse) {
option (google.api.http) = {
post: "/smtp/_test";
body: "*"
};
option (zitadel.v1.auth_option) = {
permission: "iam.write";
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags: "SMTP Provider";
summary: "Test SMTP Provider";
description: "Test an SMTP provider. After testing the provider, the users will receive information about the test results."
};
}
rpc ListSMTPConfigs(ListSMTPConfigsRequest) returns (ListSMTPConfigsResponse) {
option (google.api.http) = {
post: "/smtp/_search"
@ -4257,6 +4291,82 @@ message RemoveSMTPConfigResponse {
zitadel.v1.ObjectDetails details = 1;
}
message TestSMTPConfigByIdRequest {
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 100}];
string receiver_address = 2 [
(validate.rules).string = {min_len: 1, max_len: 200, email: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"noreply@m.zitadel.cloud\"";
min_length: 1;
max_length: 200;
}
];
}
// This is an empty response
message TestSMTPConfigByIdResponse {}
message TestSMTPConfigRequest {
string sender_address = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"noreply@m.zitadel.cloud\"";
min_length: 1;
max_length: 200;
}
];
string sender_name = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ZITADEL\"";
min_length: 1;
max_length: 200;
}
];
bool tls = 3;
string host = 4 [
(validate.rules).string = {min_len: 1, max_len: 500},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"smtp.postmarkapp.com:587\"";
description: "Make sure to include the port.";
min_length: 1;
max_length: 500;
}
];
string user = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"197f0117-529e-443d-bf6c-0292dd9a02b7\"";
}
];
string password = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"this-is-my-password\"";
}
];
string receiver_address = 7 [
(validate.rules).string = {min_len: 1, max_len: 200, email: true},
(google.api.field_behavior) = REQUIRED,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"noreply@m.zitadel.cloud\"";
min_length: 1;
max_length: 200;
}
];
string id = 8 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Zitadel SMTP provider id in case you are not sending the password and want to reuse the stored password";
example: "\"267191369515139464\"";
}
];
}
// This is an empty response
message TestSMTPConfigResponse {}
message ListSMSProvidersRequest {
//list limitations and ordering
zitadel.v1.ListQuery query = 1;