Remove email config page (#17711)

Signed-off-by: AllForNothing <sshijun@vmware.com>

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2022-11-03 14:48:06 +08:00 committed by GitHub
parent 39ca918ffe
commit 93ac2e8111
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 0 additions and 556 deletions

View File

@ -17,16 +17,6 @@
{{ 'CONFIG.AUTH' | translate }}
</button>
</li>
<li role="presentation" class="nav-item">
<button
id="config-email"
class="btn btn-link nav-link"
type="button"
routerLink="email"
routerLinkActive="active">
{{ 'CONFIG.EMAIL' | translate }}
</button>
</li>
<li role="presentation" class="nav-item">
<button
id="config-security"

View File

@ -16,7 +16,6 @@ import { NgModule } from '@angular/core';
import { SharedModule } from '../../../shared/shared.module';
import { ConfigurationComponent } from './config.component';
import { ConfigurationAuthComponent } from './auth/config-auth.component';
import { ConfigurationEmailComponent } from './email/config-email.component';
import { SystemSettingsComponent } from './system/system-settings.component';
import { RouterModule, Routes } from '@angular/router';
import { ConfigService } from './config.service';
@ -31,10 +30,6 @@ const routes: Routes = [
path: 'auth',
component: ConfigurationAuthComponent,
},
{
path: 'email',
component: ConfigurationEmailComponent,
},
{
path: 'security',
component: SecurityComponent,
@ -56,7 +51,6 @@ const routes: Routes = [
declarations: [
ConfigurationComponent,
ConfigurationAuthComponent,
ConfigurationEmailComponent,
SystemSettingsComponent,
SecurityComponent,
],

View File

@ -1,184 +0,0 @@
<form #mailConfigFrom="ngForm" class="clr-form clr-form-horizontal">
<section class="form-block">
<clr-input-container>
<label for="mailServer" class="required">{{
'CONFIG.MAIL_SERVER' | translate
}}</label>
<input
clrInput
name="mailServer"
type="text"
#mailServerInput="ngModel"
[(ngModel)]="currentConfig.email_host.value"
required
id="mailServer"
size="40"
[disabled]="disabled(currentConfig.email_host)" />
<clr-control-error>{{
'TOOLTIP.ITEM_REQUIRED' | translate
}}</clr-control-error>
</clr-input-container>
<clr-input-container>
<label for="emailPort" class="required">{{
'CONFIG.MAIL_SERVER_PORT' | translate
}}</label>
<input
clrInput
name="emailPort"
type="text"
#emailPortInput="ngModel"
[(ngModel)]="currentConfig.email_port.value"
required
port
id="emailPort"
size="40"
[disabled]="disabled(currentConfig.email_port)" />
<clr-control-error>{{
'TOOLTIP.PORT_REQUIRED' | translate
}}</clr-control-error>
</clr-input-container>
<clr-input-container>
<label for="emailUsername">{{
'CONFIG.MAIL_USERNAME' | translate
}}</label>
<input
clrInput
name="emailUsername"
type="text"
#emailUsernameInput="ngModel"
[(ngModel)]="currentConfig.email_username.value"
id="emailUsername"
size="40"
[disabled]="disabled(currentConfig.email_username)" />
</clr-input-container>
<clr-input-container>
<label for="emailPassword">{{
'CONFIG.MAIL_PASSWORD' | translate
}}</label>
<!--disable property should be consistent with 'email_username', as the back end API won't return this fielder, -->
<input
clrInput
name="emailPassword"
type="password"
#emailPasswordInput="ngModel"
[(ngModel)]="currentConfig.email_password.value"
id="emailPassword"
size="40"
[disabled]="disabled(currentConfig.email_username)" />
</clr-input-container>
<clr-input-container>
<label for="emailFrom" class="required">{{
'CONFIG.MAIL_FROM' | translate
}}</label>
<input
clrInput
name="emailFrom"
type="text"
#emailFromInput="ngModel"
[(ngModel)]="currentConfig.email_from.value"
required
id="emailFrom"
size="40"
[disabled]="disabled(currentConfig.email_from)" />
<clr-control-error>{{
'TOOLTIP.ITEM_REQUIRED' | translate
}}</clr-control-error>
</clr-input-container>
<div
class="clr-form-control"
[class.clr-form-control-disabled]="
disabled(currentConfig.email_ssl)
">
<label class="clr-control-label" for="emailSSL"
>{{ 'CONFIG.MAIL_SSL' | translate }}
<clr-tooltip>
<clr-icon
clrTooltipTrigger
shape="info-circle"
size="24"></clr-icon>
<clr-tooltip-content
clrPosition="top-right"
clrSize="lg"
*clrIfOpen>
<span>{{ 'CONFIG.SSL_TOOLTIP' | translate }}</span>
</clr-tooltip-content>
</clr-tooltip>
</label>
<div class="clr-control-container">
<div class="clr-checkbox-wrapper" id="emailSSL-wrapper">
<input
type="checkbox"
name="emailSSL"
id="emailSSL"
[(ngModel)]="currentConfig.email_ssl.value"
[disabled]="disabled(currentConfig.email_ssl)" />
<label class="clr-control-label" for="emailSSL"> </label>
</div>
</div>
</div>
<div
class="clr-form-control"
[class.clr-form-control-disabled]="
disabled(currentConfig.email_insecure)
">
<label class="clr-control-label" for="emailInsecure"
>{{ 'CONFIG.MAIL_INSECURE' | translate }}
<clr-tooltip>
<clr-icon
clrTooltipTrigger
shape="info-circle"
size="24"></clr-icon>
<clr-tooltip-content
clrPosition="top-right"
clrSize="lg"
*clrIfOpen>
<span>{{ 'CONFIG.INSECURE_TOOLTIP' | translate }}</span>
</clr-tooltip-content>
</clr-tooltip>
</label>
<div class="clr-control-container">
<div class="clr-checkbox-wrapper" id="emailInsecure-wrapper">
<input
type="checkbox"
name="emailInsecure"
id="emailInsecure"
[ngModel]="!currentConfig.email_insecure.value"
[disabled]="disabled(currentConfig.email_insecure)"
(ngModelChange)="setInsecureValue($event)" />
<label
class="clr-control-label"
for="emailInsecure"></label>
</div>
</div>
</div>
</section>
</form>
<div>
<button
type="button"
id="config_email_save"
class="btn btn-primary"
(click)="save()"
[disabled]="!isValid() || !hasChanges() || inProgress()">
{{ 'BUTTON.SAVE' | translate }}
</button>
<button
type="button"
class="btn btn-outline"
(click)="cancel()"
[disabled]="!isValid() || !hasChanges() || inProgress()">
{{ 'BUTTON.CANCEL' | translate }}
</button>
<button
type="button"
id="ping-test"
class="btn btn-outline"
(click)="testMailServer()"
[disabled]="!isMailConfigValid()">
{{ 'BUTTON.TEST_MAIL' | translate }}
</button>
<span
id="forTestingMail"
class="spinner spinner-inline"
[hidden]="hideMailTestingSpinner"></span>
</div>

View File

@ -1,90 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfigurationService } from '../../../../services/config.service';
import { ConfigurationEmailComponent } from './config-email.component';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { of } from 'rxjs';
import { ConfigService } from '../config.service';
import { SharedTestingModule } from '../../../../shared/shared.module';
import { Configuration } from '../config';
describe('ConfigurationEmailComponent', () => {
let component: ConfigurationEmailComponent;
let fixture: ComponentFixture<ConfigurationEmailComponent>;
let fakeConfigurationService = {
saveConfiguration: () => of(null),
testMailServer: () => of(null),
};
let fakeMessageHandlerService = {
showSuccess: () => null,
};
const fakeConfigService = {
config: new Configuration(),
getConfig() {
return this.config;
},
setConfig(c) {
this.config = c;
},
getOriginalConfig() {
return new Configuration();
},
getLoadingConfigStatus() {
return false;
},
updateConfig() {},
resetConfig() {},
};
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SharedTestingModule],
declarations: [ConfigurationEmailComponent],
providers: [
{
provide: MessageHandlerService,
useValue: fakeMessageHandlerService,
},
{ provide: ConfigService, useValue: fakeConfigService },
{
provide: ConfigurationService,
useValue: fakeConfigurationService,
},
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConfigurationEmailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should save configuration', async () => {
component.currentConfig.email_host.value = 'smtp.mydomain.com';
component.currentConfig.email_port.value = 25;
component.currentConfig.email_from.value = 'smtp.mydomain.com';
await fixture.whenStable();
const configEmailSaveBtn: HTMLButtonElement =
fixture.nativeElement.querySelector('#config_email_save');
component.onGoing = true;
configEmailSaveBtn.dispatchEvent(new Event('click'));
await fixture.whenStable();
expect(component.onGoing).toBeFalsy();
});
it('should ping test server', async () => {
component.currentConfig.email_host.value = 'smtp.mydomain.com';
component.currentConfig.email_port.value = 25;
component.currentConfig.email_from.value = 'smtp.mydomain.com';
await fixture.whenStable();
const pingTestBtn = fixture.nativeElement.querySelector('#ping-test');
expect(pingTestBtn).toBeTruthy();
pingTestBtn.dispatchEvent(new Event('click'));
await fixture.whenStable();
expect(component.testingMailOnGoing).toBeFalsy();
});
});

View File

@ -1,183 +0,0 @@
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { MessageHandlerService } from '../../../../shared/services/message-handler.service';
import { ConfigurationService } from '../../../../services/config.service';
import { Configuration } from '../config';
import {
isEmpty,
getChanges as getChangesFunc,
} from '../../../../shared/units/utils';
import { errorHandler } from '../../../../shared/units/shared.utils';
import { ConfigService } from '../config.service';
@Component({
selector: 'config-email',
templateUrl: 'config-email.component.html',
styleUrls: ['./config-email.component.scss', '../config.component.scss'],
})
export class ConfigurationEmailComponent implements OnInit {
testingMailOnGoing = false;
onGoing = false;
@ViewChild('mailConfigFrom', { static: true }) mailForm: NgForm;
get currentConfig(): Configuration {
return this.conf.getConfig();
}
set currentConfig(c: Configuration) {
this.conf.setConfig(c);
}
constructor(
private msgHandler: MessageHandlerService,
private configService: ConfigurationService,
private conf: ConfigService
) {}
ngOnInit(): void {
this.conf.resetConfig();
}
disabled(prop: any): boolean {
return !(prop && prop.editable);
}
setInsecureValue($event: any) {
this.currentConfig.email_insecure.value = !$event;
}
isValid(): boolean {
return this.mailForm && this.mailForm.valid;
}
inProgress(): boolean {
return this.onGoing || this.conf.getLoadingConfigStatus();
}
public hasChanges(): boolean {
return !isEmpty(this.getChanges());
}
public getChanges() {
let allChanges = getChangesFunc(
this.conf.getOriginalConfig(),
this.currentConfig
);
let changes = {};
for (let prop in allChanges) {
if (prop.startsWith('email_')) {
changes[prop] = allChanges[prop];
}
}
return changes;
}
/**
*
* Test the connection of specified mail server
*
*
* @memberOf ConfigurationComponent
*/
public testMailServer(): void {
if (this.testingMailOnGoing) {
return; // Should not come here
}
let mailSettings = {};
for (let prop in this.currentConfig) {
if (prop.startsWith('email_')) {
mailSettings[prop] = this.currentConfig[prop].value;
}
}
// Confirm port is number
mailSettings['email_port'] = +mailSettings['email_port'];
let allChanges = this.getChanges();
let password = allChanges['email_password'];
if (password) {
mailSettings['email_password'] = password;
} else {
delete mailSettings['email_password'];
}
this.testingMailOnGoing = true;
this.configService.testMailServer(mailSettings).subscribe(
response => {
this.testingMailOnGoing = false;
this.msgHandler.showSuccess('CONFIG.TEST_MAIL_SUCCESS');
},
error => {
this.testingMailOnGoing = false;
let err = errorHandler(error);
if (!err) {
err = 'UNKNOWN';
}
this.msgHandler.showError('CONFIG.TEST_MAIL_FAILED', {
param: err,
});
}
);
}
public get hideMailTestingSpinner(): boolean {
return !this.testingMailOnGoing;
}
public isMailConfigValid(): boolean {
return this.isValid() && !this.testingMailOnGoing && !this.inProgress();
}
/**
*
* Save the changed values
*
* @memberOf ConfigurationComponent
*/
public save(): void {
let changes = this.getChanges();
if (!isEmpty(changes)) {
this.onGoing = true;
this.configService.saveConfiguration(changes).subscribe(
response => {
this.onGoing = false;
// refresh allConfig
this.conf.updateConfig();
this.msgHandler.showSuccess('CONFIG.SAVE_SUCCESS');
},
error => {
this.onGoing = false;
this.msgHandler.handleError(error);
}
);
} else {
// Inprop situation, should not come here
console.error('Save abort because nothing changed');
}
}
/**
*
* Discard current changes if have and reset
*
* @memberOf ConfigurationComponent
*/
public cancel(): void {
let changes = this.getChanges();
if (!isEmpty(changes)) {
this.conf.confirmUnsavedChanges(changes);
} else {
// Invalid situation, should not come here
console.error('Nothing changed');
}
}
}

View File

@ -857,7 +857,6 @@
"TITLE": "Konfiguration",
"AUTH": "Authentifizierung",
"REPLICATION": "Replikation",
"EMAIL": "E-Mail",
"LABEL": "Label",
"REPOSITORY": "Repository",
"REPO_READ_ONLY": "Repository Read Only",
@ -869,15 +868,6 @@
"CONFIRM_TITLE": "Bestätigen um abzubrechen",
"CONFIRM_SUMMARY": "Einige Änderungen wurden noch nicht gespeichert. Sollen diese verworfen werden?",
"SAVE_SUCCESS": "Konfiguration erfolgreich gespeichert",
"MAIL_SERVER": "E-Mail Server",
"MAIL_SERVER_PORT": "E-Mail Server Port",
"MAIL_USERNAME": "E-Mail Nutzername",
"MAIL_PASSWORD": "E-Mail Passwort",
"MAIL_FROM": "E-Mail von",
"MAIL_SSL": "E-Mail SSL",
"MAIL_INSECURE": "Zertifikat überprüfen",
"INSECURE_TOOLTIP": "Festlegen, ob das Zertifikat des E-Mail-Servers überprüft werden soll. Deaktiviere die Box, wenn der E-Mail-Server ein selbstsigniertes oder nicht-vertrauenswürdiges Zertifikat verwendet.",
"SSL_TOOLTIP": "TLS für E-Mail Verbindung aktivieren",
"VERIFY_REMOTE_CERT": "Zertifikat der Gegenstelle prüfen",
"TOKEN_EXPIRATION": "Token-Ablauf (Minuten)",
"AUTH_MODE": "Auth Mode",

View File

@ -857,7 +857,6 @@
"TITLE": "Configuration",
"AUTH": "Authentication",
"REPLICATION": "Replication",
"EMAIL": "Email",
"LABEL": "Labels",
"REPOSITORY": "Repository",
"REPO_READ_ONLY": "Repository Read Only",
@ -869,15 +868,6 @@
"CONFIRM_TITLE": "Confirm to cancel",
"CONFIRM_SUMMARY": "Some changes have not been saved. Do you want to discard them?",
"SAVE_SUCCESS": "Configuration has been successfully saved.",
"MAIL_SERVER": "Email Server",
"MAIL_SERVER_PORT": "Email Server Port",
"MAIL_USERNAME": "Email Username",
"MAIL_PASSWORD": "Email Password",
"MAIL_FROM": "Email From",
"MAIL_SSL": "Email SSL",
"MAIL_INSECURE": "Verify Certificate",
"INSECURE_TOOLTIP": "Determine whether to verify the certificate of the Email server. Uncheck this box when the Email server uses a self-signed or untrusted certificate.",
"SSL_TOOLTIP": "Enable SSL for email server connection",
"VERIFY_REMOTE_CERT": "Verify Remote Cert",
"TOKEN_EXPIRATION": "Token Expiration (Minutes)",
"AUTH_MODE": "Auth Mode",

View File

@ -859,7 +859,6 @@
"TITLE": "Configuración",
"AUTH": "Autentificación",
"REPLICATION": "Replicación",
"EMAIL": "Email",
"LABEL": "Labels",
"REPOSITORY": "Repository",
"REPO_READ_ONLY": "Repository Read Only",
@ -870,15 +869,6 @@
"CONFIRM_TITLE": "Confirma cancelación",
"CONFIRM_SUMMARY": "Algunos cambios no han sido guardados aún. ¿Quiere descartarlos?",
"SAVE_SUCCESS": "La configuración ha sido guardada satisfactoriamente.",
"MAIL_SERVER": "Servidor de email",
"MAIL_SERVER_PORT": "Puerto del servidor de email",
"MAIL_USERNAME": "Usuario del servidor de email",
"MAIL_PASSWORD": "Contraseña del servidor de email",
"MAIL_FROM": "Email De",
"MAIL_SSL": "Email SSL",
"MAIL_INSECURE": "Verify Certificate",
"INSECURE_TOOLTIP": "Determine whether to verify the certificate of the Email server. Uncheck this box when the Email server uses a self-signed or untrusted certificate.",
"SSL_TOOLTIP": "Activar SSL en conexiones al servidor de correo",
"VERIFY_REMOTE_CERT": "Verificar Certificado Remoto",
"TOKEN_EXPIRATION": "Expiración del Token (Minutos)",
"AUTH_MODE": "Modo de autentificación",

View File

@ -843,22 +843,12 @@
"TITLE": "Configuration",
"AUTH": "Identification",
"REPLICATION": "Réplication",
"EMAIL": "Email",
"LABEL": "Labels",
"SYSTEM": "Réglages Système",
"PROJECT_QUOTAS": "Quotas de projet",
"CONFIRM_TITLE": "Confirmer pour annuler",
"CONFIRM_SUMMARY": "Certaines modifications n'ont pas été sauvegardées. Voulez-vous les annuler ?",
"SAVE_SUCCESS": "La configuration a été sauvegardée avec succès.",
"MAIL_SERVER": "Serveur mail",
"MAIL_SERVER_PORT": "Port du Serveur mail",
"MAIL_USERNAME": "Nom d'Utilisateur du compte mail",
"MAIL_PASSWORD": "Mot de passe du compte mail",
"MAIL_FROM": "Email de",
"MAIL_SSL": "Email avec SSL",
"MAIL_INSECURE": "Vérifier le Certificat",
"INSECURE_TOOLTIP": "Déterminez s'il faut vérifier le certificat du serveur mail. Décochez cette case lorsque le serveur mail utilise un certificat auto-signé ou non approuvé.",
"SSL_TOOLTIP": "Activer SSL lors de la connexion au serveur mail",
"VERIFY_REMOTE_CERT": "Vérifier le Certificat Distant",
"TOKEN_EXPIRATION": "Expiration du Jeton (Minutes)",
"AUTH_MODE": "Mode d'Identification",

View File

@ -854,7 +854,6 @@
"TITLE": "Configuração",
"AUTH": "Autenticação",
"REPLICATION": "Replicação",
"EMAIL": "E-mail",
"LABEL": "Marcadores",
"REPOSITORY": "Repositório",
"REPO_READ_ONLY": "Repositório somente leitura",
@ -865,15 +864,6 @@
"CONFIRM_TITLE": "Confirmação de cancelamento",
"CONFIRM_SUMMARY": "Algumas alterações não foram salvas. Deseja descartá-las?",
"SAVE_SUCCESS": "Configuração salva com sucesso.",
"MAIL_SERVER": "Servidor de E-mail",
"MAIL_SERVER_PORT": "Porta do Servidor de E-mail",
"MAIL_USERNAME": "Nome de usuário do Servidor de E-mail",
"MAIL_PASSWORD": "Senha do servidor de E-mail",
"MAIL_FROM": "E-mail de",
"MAIL_SSL": "SSL do E-mail",
"MAIL_INSECURE": "Verificar certificados",
"INSECURE_TOOLTIP": "Determina se o certificado do servidor de E-mail deve ser verificado. Desmarque esse item quando o servidor de E-mail utiliza um certificado auto-assinado ou não confiável.",
"SSL_TOOLTIP": "Habilitar SSL para conexão ao servidor de E-mail",
"VERIFY_REMOTE_CERT": "Verificar Certificado remoto",
"TOKEN_EXPIRATION": "Expiração do Token (Minutos)",
"AUTH_MODE": "Modo de autenticação",

View File

@ -857,7 +857,6 @@
"TITLE": "Ayarlar",
"AUTH": "Doğrulama",
"REPLICATION": "Kopya",
"EMAIL": "E-posta",
"LABEL": "Etiketler",
"REPOSITORY": "Depo",
"REPO_READ_ONLY": "Depo Salt Okunur",
@ -869,15 +868,6 @@
"CONFIRM_TITLE": "İptal etmeyi onayla",
"CONFIRM_SUMMARY": "Bazı değişiklikler kaydedilmedi. Onları silmek ister misin?",
"SAVE_SUCCESS": "Yapılandırma başarıyla kaydedildi.",
"MAIL_SERVER": "E-posta Sunucusu",
"MAIL_SERVER_PORT": "E-posta Sunucu Portu",
"MAIL_USERNAME": "E-posta Kullanıcı Adı",
"MAIL_PASSWORD": "E-posta Şifresi",
"MAIL_FROM": "E-posta kimden",
"MAIL_SSL": "E-posta SSL",
"MAIL_INSECURE": "Sertifikayı Doğrula",
"INSECURE_TOOLTIP": "E-posta sunucusunun sertifikasının doğrulanıp doğrulanmayacağını belirleyin. E-posta sunucusu kendinden imzalı veya güvenilmeyen bir sertifika kullandığında bu kutunun işaretini kaldırın.",
"SSL_TOOLTIP": "E-posta sunucusu bağlantısı için SSL'yi etkinleştir",
"VERIFY_REMOTE_CERT": "Uzaktan Sertifikayı Doğrula",
"TOKEN_EXPIRATION": "Token Sonu (Dakika)",
"AUTH_MODE": "Yetkilendirme Modu",

View File

@ -859,7 +859,6 @@
"TITLE": "配置",
"AUTH": "认证模式",
"REPLICATION": "复制",
"EMAIL": "邮箱",
"LABEL": "标签",
"REPOSITORY": "仓库",
"REPO_READ_ONLY": "仓库只读",
@ -871,15 +870,6 @@
"CONFIRM_TITLE": "确认取消",
"CONFIRM_SUMMARY": "配置项有改动, 确定取消?",
"SAVE_SUCCESS": "变更的配置项成功保存。",
"MAIL_SERVER": "邮件服务器",
"MAIL_SERVER_PORT": "邮件服务器端口",
"MAIL_USERNAME": "用户名",
"MAIL_PASSWORD": "密码",
"MAIL_FROM": "邮件来源",
"MAIL_SSL": "邮件 SSL",
"MAIL_INSECURE": "验证证书",
"INSECURE_TOOLTIP": "确定是否要验证邮件服务器的证书。如果邮件服务器使用的是自签或者非信任证书,不要勾选此项。",
"SSL_TOOLTIP": "启用SSL到邮件服务器连接。",
"VERIFY_REMOTE_CERT": "验证远程证书",
"TOKEN_EXPIRATION": "令牌过期时间(分钟)",
"AUTH_MODE": "认证模式",

View File

@ -854,7 +854,6 @@
"TITLE": "配置",
"AUTH": "認證模式",
"REPLICATION": "複製",
"EMAIL": "郵箱",
"LABEL": "標籤",
"REPOSITORY": "倉庫",
"REPO_READ_ONLY": "倉庫只讀",
@ -866,15 +865,6 @@
"CONFIRM_TITLE": "確認取消",
"CONFIRM_SUMMARY": "配置項有改動, 確定取消?",
"SAVE_SUCCESS": "變更的配置項成功保存。",
"MAIL_SERVER": "郵件服務器",
"MAIL_SERVER_PORT": "郵件服務器端口",
"MAIL_USERNAME": "用戶名",
"MAIL_PASSWORD": "密碼",
"MAIL_FROM": "郵件來源",
"MAIL_SSL": "郵件SSL",
"MAIL_INSECURE": "驗證證書",
"INSECURE_TOOLTIP": "確定是否要驗證郵件服務器的證書。如果郵件服務器使用的是自籤或者非信任證書,不要勾選此項。",
"SSL_TOOLTIP": "啟用SSL到郵件服務器連接。",
"VERIFY_REMOTE_CERT": "驗證遠程證書",
"TOKEN_EXPIRATION": "令牌過期時間(分鐘)",
"AUTH_MODE": "認證模式",