First commit waiting for Budget Alert
This commit is contained in:
16
modules/axelor-open-suite/axelor-message/build.gradle
Normal file
16
modules/axelor-open-suite/axelor-message/build.gradle
Normal file
@ -0,0 +1,16 @@
|
||||
apply plugin: "com.axelor.app-module"
|
||||
|
||||
apply from: "../version.gradle"
|
||||
|
||||
apply {
|
||||
version = openSuiteVersion
|
||||
}
|
||||
|
||||
axelor {
|
||||
title "Axelor Message"
|
||||
description "Axelor Message Module"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(":modules:axelor-tool")
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.db.repo;
|
||||
|
||||
import com.axelor.apps.message.db.Message;
|
||||
|
||||
public class MessageManagementRepository extends MessageRepository {
|
||||
@Override
|
||||
public Message copy(Message entity, boolean deep) {
|
||||
entity.setStatusSelect(1);
|
||||
entity.setSentDateT(null);
|
||||
entity.setToEmailAddressSet(null);
|
||||
entity.setCcEmailAddressSet(null);
|
||||
entity.setBccEmailAddressSet(null);
|
||||
entity.setRecipientUser(null);
|
||||
return super.copy(entity, deep);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/** */
|
||||
package com.axelor.apps.message.exception;
|
||||
|
||||
/** @author axelor */
|
||||
public interface IExceptionMessage {
|
||||
|
||||
/** Mail account service and controller */
|
||||
static final String MAIL_ACCOUNT_1 = /*$$(*/ "Incorrect login or password" /*)*/;
|
||||
|
||||
static final String MAIL_ACCOUNT_2 = /*$$(*/
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS" /*)*/;
|
||||
static final String MAIL_ACCOUNT_3 = /*$$(*/ "Connection successful" /*)*/;
|
||||
static final String MAIL_ACCOUNT_4 = /*$$(*/
|
||||
"Provided settings are wrong, please modify them and try again" /*)*/;
|
||||
static final String MAIL_ACCOUNT_5 = /*$$(*/ "There is already a default account" /*)*/;
|
||||
|
||||
/** Template service */
|
||||
static final String TEMPLATE_SERVICE_1 = /*$$(*/ "Model empty. Please configure a model." /*)*/;
|
||||
|
||||
static final String TEMPLATE_SERVICE_2 = /*$$(*/
|
||||
"Your target receptor is not valid. Please check it." /*)*/;
|
||||
static final String TEMPLATE_SERVICE_3 = /*$$(*/ "Waiting model: %s" /*)*/;
|
||||
|
||||
/** General message controller */
|
||||
static final String MESSAGE_1 = /*$$(*/ "Please configure a template" /*)*/;
|
||||
|
||||
static final String MESSAGE_2 = /*$$(*/ "Select template" /*)*/;
|
||||
static final String MESSAGE_3 = /*$$(*/ "Create message" /*)*/;
|
||||
static final String MESSAGE_4 = /*$$(*/ "Email sending is in progress" /*)*/;
|
||||
static final String MESSAGE_5 = /*$$(*/ "Sender's email address is null or empty" /*)*/;
|
||||
static final String MESSAGE_6 = /*$$(*/ "TO/CC/BCC recipient's email address is empty" /*)*/;
|
||||
static final String MESSAGE_MISSING_SELECTED_MESSAGES = /*$$(*/
|
||||
"Please select one or more messages." /*)*/;
|
||||
static final String MESSAGES_SEND_IN_PROGRESS = /*$$(*/
|
||||
"Email sending is in progress for %d messages." /*)*/;
|
||||
static final String MESSAGES_REGENERATED = /*$$(*/
|
||||
"%d messages has been regenerated successfully and %d errors append." /*)*/;
|
||||
static final String SET_EMAIL_TEMPLATE_MESSAGE = /*$$(*/
|
||||
"Please set the email template to send" /*)*/;
|
||||
static final String INVALID_MODEL_TEMPLATE_EMAIL = /*$$(*/
|
||||
"The email template model (%s) is different than the entity generating the email (%s)" /*)*/;
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.job;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.repo.EmailAccountRepository;
|
||||
import com.axelor.apps.message.service.MailAccountService;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.mail.MessagingException;
|
||||
import org.quartz.Job;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** An example {@link Job} class that prints a some messages to the stderr. */
|
||||
public class FetchEmailJob implements Job {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(FetchEmailJob.class);
|
||||
|
||||
@Inject private MailAccountService mailAccountService;
|
||||
|
||||
@Inject private EmailAccountRepository mailAccountRepo;
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) {
|
||||
|
||||
List<EmailAccount> mailAccounts =
|
||||
mailAccountRepo.all().filter("self.isValid = true and self.serverTypeSelect > 1").fetch();
|
||||
|
||||
log.debug("Total email fetching accounts : {}", mailAccounts.size());
|
||||
for (EmailAccount account : mailAccounts) {
|
||||
try {
|
||||
Integer total = mailAccountService.fetchEmails(account, true);
|
||||
log.debug("Email fetched for account: {}, total: {} ", account.getName(), total);
|
||||
} catch (MessagingException | IOException e) {
|
||||
TraceBackService.trace(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.module;
|
||||
|
||||
import com.axelor.app.AxelorModule;
|
||||
import com.axelor.apps.message.db.repo.MessageManagementRepository;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.service.MailAccountService;
|
||||
import com.axelor.apps.message.service.MailAccountServiceImpl;
|
||||
import com.axelor.apps.message.service.MailServiceMessageImpl;
|
||||
import com.axelor.apps.message.service.MessageService;
|
||||
import com.axelor.apps.message.service.MessageServiceImpl;
|
||||
import com.axelor.apps.message.service.TemplateMessageService;
|
||||
import com.axelor.apps.message.service.TemplateMessageServiceImpl;
|
||||
import com.axelor.mail.service.MailServiceImpl;
|
||||
|
||||
public class MessageModule extends AxelorModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(TemplateMessageService.class).to(TemplateMessageServiceImpl.class);
|
||||
bind(MessageService.class).to(MessageServiceImpl.class);
|
||||
bind(MessageRepository.class).to(MessageManagementRepository.class);
|
||||
bind(MailAccountService.class).to(MailAccountServiceImpl.class);
|
||||
bind(MailServiceImpl.class).to(MailServiceMessageImpl.class);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.mail.MailAccount;
|
||||
import java.io.IOException;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
public interface MailAccountService {
|
||||
|
||||
public void checkDefaultMailAccount(EmailAccount mailAccount) throws AxelorException;
|
||||
|
||||
public EmailAccount getDefaultSender();
|
||||
|
||||
public EmailAccount getDefaultReader();
|
||||
|
||||
public void checkMailAccountConfiguration(EmailAccount mailAccount)
|
||||
throws AxelorException, MessagingException;
|
||||
|
||||
public String getSecurity(EmailAccount mailAccount);
|
||||
|
||||
public String getProtocol(EmailAccount mailAccount);
|
||||
|
||||
public String getSignature(EmailAccount mailAccount);
|
||||
|
||||
public String getEncryptPassword(String password);
|
||||
|
||||
public String getDecryptPassword(String password);
|
||||
|
||||
public int fetchEmails(EmailAccount mailAccount, boolean unseenOnly)
|
||||
throws MessagingException, IOException;
|
||||
|
||||
public MailAccount getMailAccount(EmailAccount mailAccount);
|
||||
}
|
||||
@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.EmailAddress;
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.repo.EmailAccountRepository;
|
||||
import com.axelor.apps.message.db.repo.EmailAddressRepository;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.apps.tool.date.DateTool;
|
||||
import com.axelor.apps.tool.service.CipherService;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.mail.ImapAccount;
|
||||
import com.axelor.mail.MailConstants;
|
||||
import com.axelor.mail.MailParser;
|
||||
import com.axelor.mail.MailReader;
|
||||
import com.axelor.mail.Pop3Account;
|
||||
import com.axelor.mail.SmtpAccount;
|
||||
import com.axelor.meta.MetaFiles;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.activation.DataSource;
|
||||
import javax.mail.AuthenticationFailedException;
|
||||
import javax.mail.FetchProfile;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.NoSuchProviderException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.search.FlagTerm;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MailAccountServiceImpl implements MailAccountService {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(MailAccountServiceImpl.class);
|
||||
|
||||
static final int CHECK_CONF_TIMEOUT = 5000;
|
||||
|
||||
@Inject protected EmailAccountRepository mailAccountRepo;
|
||||
|
||||
@Inject private CipherService cipherService;
|
||||
|
||||
@Inject protected EmailAddressRepository emailAddressRepo;
|
||||
|
||||
@Inject private MessageRepository messageRepo;
|
||||
|
||||
@Inject private MetaFiles metaFiles;
|
||||
|
||||
@Override
|
||||
public void checkDefaultMailAccount(EmailAccount mailAccount) throws AxelorException {
|
||||
|
||||
if (mailAccount.getIsDefault()) {
|
||||
String query = "self.isDefault = true";
|
||||
List<Object> params = Lists.newArrayList();
|
||||
if (mailAccount.getId() != null) {
|
||||
query += " AND self.id != ?1";
|
||||
params.add(mailAccount.getId());
|
||||
}
|
||||
|
||||
Integer serverTypeSelect = mailAccount.getServerTypeSelect();
|
||||
if (serverTypeSelect == EmailAccountRepository.SERVER_TYPE_SMTP) {
|
||||
query += " AND self.serverTypeSelect = " + EmailAccountRepository.SERVER_TYPE_SMTP + " ";
|
||||
} else if (serverTypeSelect == EmailAccountRepository.SERVER_TYPE_IMAP
|
||||
|| serverTypeSelect == EmailAccountRepository.SERVER_TYPE_POP) {
|
||||
query +=
|
||||
" AND (self.serverTypeSelect = "
|
||||
+ EmailAccountRepository.SERVER_TYPE_IMAP
|
||||
+ " OR "
|
||||
+ "self.serverTypeSelect = "
|
||||
+ EmailAccountRepository.SERVER_TYPE_POP
|
||||
+ ") ";
|
||||
}
|
||||
|
||||
Long count = mailAccountRepo.all().filter(query, params.toArray()).count();
|
||||
if (count > 0) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||
I18n.get(IExceptionMessage.MAIL_ACCOUNT_5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAccount getDefaultSender() {
|
||||
|
||||
return mailAccountRepo
|
||||
.all()
|
||||
.filter(
|
||||
"self.isDefault = true AND self.serverTypeSelect = ?1",
|
||||
EmailAccountRepository.SERVER_TYPE_SMTP)
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailAccount getDefaultReader() {
|
||||
|
||||
return mailAccountRepo
|
||||
.all()
|
||||
.filter(
|
||||
"self.isDefault = true "
|
||||
+ "AND (self.serverTypeSelect = ?1 OR self.serverTypeSelect = ?2)",
|
||||
EmailAccountRepository.SERVER_TYPE_IMAP,
|
||||
EmailAccountRepository.SERVER_TYPE_POP)
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMailAccountConfiguration(EmailAccount mailAccount)
|
||||
throws AxelorException, MessagingException {
|
||||
|
||||
com.axelor.mail.MailAccount account = getMailAccount(mailAccount);
|
||||
|
||||
Session session = account.getSession();
|
||||
|
||||
try {
|
||||
|
||||
if (mailAccount.getServerTypeSelect().equals(EmailAccountRepository.SERVER_TYPE_SMTP)) {
|
||||
Transport transport = session.getTransport(getProtocol(mailAccount));
|
||||
transport.connect(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort(),
|
||||
mailAccount.getLogin(),
|
||||
mailAccount.getPassword());
|
||||
transport.close();
|
||||
} else {
|
||||
session.getStore().connect();
|
||||
}
|
||||
|
||||
} catch (AuthenticationFailedException e) {
|
||||
throw new AxelorException(
|
||||
e,
|
||||
mailAccount,
|
||||
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||
I18n.get(IExceptionMessage.MAIL_ACCOUNT_1));
|
||||
} catch (NoSuchProviderException e) {
|
||||
throw new AxelorException(
|
||||
e,
|
||||
mailAccount,
|
||||
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||
I18n.get(IExceptionMessage.MAIL_ACCOUNT_2));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.axelor.mail.MailAccount getMailAccount(EmailAccount mailAccount) {
|
||||
|
||||
Integer serverType = mailAccount.getServerTypeSelect();
|
||||
|
||||
String port = mailAccount.getPort() <= 0 ? null : mailAccount.getPort().toString();
|
||||
|
||||
com.axelor.mail.MailAccount account;
|
||||
|
||||
if (serverType == EmailAccountRepository.SERVER_TYPE_SMTP) {
|
||||
account =
|
||||
new SmtpAccount(
|
||||
mailAccount.getHost(),
|
||||
port,
|
||||
mailAccount.getLogin(),
|
||||
getDecryptPassword(mailAccount.getPassword()),
|
||||
getSecurity(mailAccount));
|
||||
} else if (serverType == EmailAccountRepository.SERVER_TYPE_IMAP) {
|
||||
account =
|
||||
new ImapAccount(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort().toString(),
|
||||
mailAccount.getLogin(),
|
||||
getDecryptPassword(mailAccount.getPassword()),
|
||||
getSecurity(mailAccount));
|
||||
} else {
|
||||
account =
|
||||
new Pop3Account(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort().toString(),
|
||||
mailAccount.getLogin(),
|
||||
getDecryptPassword(mailAccount.getPassword()),
|
||||
getSecurity(mailAccount));
|
||||
}
|
||||
|
||||
account.setConnectionTimeout(CHECK_CONF_TIMEOUT);
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getSecurity(EmailAccount mailAccount) {
|
||||
|
||||
if (mailAccount.getSecuritySelect() == EmailAccountRepository.SECURITY_SSL) {
|
||||
return MailConstants.CHANNEL_SSL;
|
||||
} else if (mailAccount.getSecuritySelect() == EmailAccountRepository.SECURITY_STARTTLS) {
|
||||
return MailConstants.CHANNEL_STARTTLS;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getProtocol(EmailAccount mailAccount) {
|
||||
|
||||
switch (mailAccount.getServerTypeSelect()) {
|
||||
case EmailAccountRepository.SERVER_TYPE_SMTP:
|
||||
return "smtp";
|
||||
case EmailAccountRepository.SERVER_TYPE_IMAP:
|
||||
if (mailAccount.getSecuritySelect() == EmailAccountRepository.SECURITY_SSL) {
|
||||
return MailConstants.PROTOCOL_IMAPS;
|
||||
}
|
||||
return MailConstants.PROTOCOL_IMAP;
|
||||
case EmailAccountRepository.SERVER_TYPE_POP:
|
||||
return MailConstants.PROTOCOL_POP3;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getSignature(EmailAccount mailAccount) {
|
||||
|
||||
if (mailAccount != null && mailAccount.getSignature() != null) {
|
||||
return "\n " + mailAccount.getSignature();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fetchEmails(EmailAccount mailAccount, boolean unseenOnly)
|
||||
throws MessagingException, IOException {
|
||||
|
||||
if (mailAccount == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
log.debug(
|
||||
"Fetching emails from host: {}, port: {}, login: {} ",
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort(),
|
||||
mailAccount.getLogin());
|
||||
|
||||
com.axelor.mail.MailAccount account = null;
|
||||
if (mailAccount.getServerTypeSelect().equals(EmailAccountRepository.SERVER_TYPE_IMAP)) {
|
||||
account =
|
||||
new ImapAccount(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort().toString(),
|
||||
mailAccount.getLogin(),
|
||||
mailAccount.getPassword(),
|
||||
getSecurity(mailAccount));
|
||||
} else {
|
||||
account =
|
||||
new Pop3Account(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort().toString(),
|
||||
mailAccount.getLogin(),
|
||||
mailAccount.getPassword(),
|
||||
getSecurity(mailAccount));
|
||||
}
|
||||
|
||||
MailReader reader = new MailReader(account);
|
||||
final Store store = reader.getStore();
|
||||
final Folder inbox = store.getFolder("INBOX");
|
||||
|
||||
// open as READ_WRITE to mark messages as seen
|
||||
inbox.open(Folder.READ_WRITE);
|
||||
|
||||
// find all unseen messages
|
||||
final FetchProfile profile = new FetchProfile();
|
||||
javax.mail.Message[] messages;
|
||||
if (unseenOnly) {
|
||||
final FlagTerm unseen = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
|
||||
messages = inbox.search(unseen);
|
||||
} else {
|
||||
messages = inbox.getMessages();
|
||||
}
|
||||
|
||||
profile.add(FetchProfile.Item.ENVELOPE);
|
||||
|
||||
// actually fetch the messages
|
||||
inbox.fetch(messages, profile);
|
||||
log.debug("Total emails unseen: {}", messages.length);
|
||||
|
||||
int count = 0;
|
||||
for (javax.mail.Message message : messages) {
|
||||
if (message instanceof MimeMessage) {
|
||||
MailParser parser = new MailParser((MimeMessage) message);
|
||||
parser.parse();
|
||||
createMessage(mailAccount, parser, message.getSentDate());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("Total emails fetched: {}", count);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Message createMessage(EmailAccount mailAccount, MailParser parser, Date date)
|
||||
throws MessagingException {
|
||||
|
||||
Message message = new Message();
|
||||
|
||||
message.setMailAccount(mailAccount);
|
||||
message.setTypeSelect(MessageRepository.TYPE_SENT);
|
||||
message.setMediaTypeSelect(MessageRepository.MEDIA_TYPE_EMAIL);
|
||||
|
||||
message.setFromEmailAddress(getEmailAddress(parser.getFrom()));
|
||||
message.setCcEmailAddressSet(getEmailAddressSet(parser.getCc()));
|
||||
message.setBccEmailAddressSet(getEmailAddressSet(parser.getBcc()));
|
||||
message.setToEmailAddressSet(getEmailAddressSet(parser.getTo()));
|
||||
message.addReplyToEmailAddressSetItem(getEmailAddress(parser.getReplyTo()));
|
||||
|
||||
message.setContent(parser.getHtml());
|
||||
message.setSubject(parser.getSubject());
|
||||
message.setSentDateT(DateTool.toLocalDateT(date));
|
||||
|
||||
message = messageRepo.save(message);
|
||||
|
||||
List<DataSource> attachments = parser.getAttachments();
|
||||
addAttachments(message, attachments);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private EmailAddress getEmailAddress(InternetAddress address) {
|
||||
|
||||
EmailAddress emailAddress = null;
|
||||
emailAddress = emailAddressRepo.findByAddress(address.getAddress());
|
||||
if (emailAddress == null) {
|
||||
emailAddress = new EmailAddress();
|
||||
emailAddress.setAddress(address.getAddress());
|
||||
}
|
||||
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
private Set<EmailAddress> getEmailAddressSet(List<InternetAddress> addresses) {
|
||||
|
||||
Set<EmailAddress> addressSet = new HashSet<>();
|
||||
|
||||
if (addresses == null) {
|
||||
return addressSet;
|
||||
}
|
||||
|
||||
for (InternetAddress address : addresses) {
|
||||
|
||||
EmailAddress emailAddress = getEmailAddress(address);
|
||||
|
||||
addressSet.add(emailAddress);
|
||||
}
|
||||
|
||||
return addressSet;
|
||||
}
|
||||
|
||||
private void addAttachments(Message message, List<DataSource> attachments) {
|
||||
|
||||
if (attachments == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (DataSource source : attachments) {
|
||||
try {
|
||||
InputStream stream = source.getInputStream();
|
||||
metaFiles.attach(stream, source.getName(), message);
|
||||
} catch (IOException e) {
|
||||
TraceBackService.trace(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncryptPassword(String password) {
|
||||
|
||||
return cipherService.encrypt(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDecryptPassword(String password) {
|
||||
|
||||
return cipherService.decrypt(password);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import static com.axelor.common.StringUtils.isBlank;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.EmailAddress;
|
||||
import com.axelor.apps.message.db.repo.EmailAddressRepository;
|
||||
import com.axelor.auth.AuditableRunner;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.mail.MailAccount;
|
||||
import com.axelor.mail.MailBuilder;
|
||||
import com.axelor.mail.MailException;
|
||||
import com.axelor.mail.MailReader;
|
||||
import com.axelor.mail.MailSender;
|
||||
import com.axelor.mail.db.MailMessage;
|
||||
import com.axelor.mail.db.repo.MailMessageRepository;
|
||||
import com.axelor.mail.service.MailService;
|
||||
import com.axelor.mail.service.MailServiceImpl;
|
||||
import com.axelor.meta.MetaFiles;
|
||||
import com.axelor.meta.db.MetaAttachment;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import javax.inject.Singleton;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class MailServiceMessageImpl extends MailServiceImpl {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(MailService.class);
|
||||
|
||||
private ExecutorService executor = Executors.newCachedThreadPool();
|
||||
|
||||
private MailSender sender = null;
|
||||
|
||||
private MailReader reader = null;
|
||||
|
||||
private EmailAccount senderAccount = null;
|
||||
|
||||
private EmailAccount readerAccount = null;
|
||||
|
||||
@Inject private MailAccountService mailAccountService;
|
||||
|
||||
@Override
|
||||
public Model resolve(String email) {
|
||||
final EmailAddressRepository addresses = Beans.get(EmailAddressRepository.class);
|
||||
final EmailAddress address = addresses.all().filter("self.address = ?1", email).fetchOne();
|
||||
if (address != null) {
|
||||
return address;
|
||||
}
|
||||
return super.resolve(email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InternetAddress> findEmails(String matching, List<String> selected, int maxResult) {
|
||||
|
||||
final List<String> where = new ArrayList<>();
|
||||
final Map<String, Object> params = new HashMap<>();
|
||||
|
||||
where.add("self.address is not null");
|
||||
|
||||
if (!isBlank(matching)) {
|
||||
where.add("(LOWER(self.address) like LOWER(:email))");
|
||||
params.put("email", "%" + matching + "%");
|
||||
}
|
||||
if (selected != null && !selected.isEmpty()) {
|
||||
where.add("self.address not in (:selected)");
|
||||
params.put("selected", selected);
|
||||
}
|
||||
|
||||
final String filter = Joiner.on(" AND ").join(where);
|
||||
final Query<EmailAddress> query = Query.of(EmailAddress.class);
|
||||
|
||||
if (!isBlank(filter)) {
|
||||
query.filter(filter);
|
||||
query.bind(params);
|
||||
}
|
||||
|
||||
final List<InternetAddress> addresses = new ArrayList<>();
|
||||
for (EmailAddress emailAddress : query.fetch(maxResult)) {
|
||||
try {
|
||||
final InternetAddress item = new InternetAddress(emailAddress.getAddress());
|
||||
addresses.add(item);
|
||||
} catch (AddressException e) {
|
||||
}
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch() throws MailException {
|
||||
|
||||
final EmailAccount emailAccount = mailAccountService.getDefaultReader();
|
||||
if (emailAccount == null) {
|
||||
super.fetch();
|
||||
} else {
|
||||
final MailReader reader = getMailReader(emailAccount);
|
||||
final AuditableRunner runner = Beans.get(AuditableRunner.class);
|
||||
runner.run(
|
||||
() -> {
|
||||
try {
|
||||
fetch(reader);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to fetch messages", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final MailMessage message) throws MailException {
|
||||
final EmailAccount emailAccount = mailAccountService.getDefaultSender();
|
||||
if (emailAccount == null) {
|
||||
super.send(message);
|
||||
return;
|
||||
}
|
||||
|
||||
Preconditions.checkNotNull(message, "mail message can't be null");
|
||||
|
||||
final Model related = findEntity(message);
|
||||
final MailSender sender = getMailSender(emailAccount);
|
||||
|
||||
final Set<String> recipients = recipients(message, related);
|
||||
if (recipients.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final MailMessageRepository messages = Beans.get(MailMessageRepository.class);
|
||||
final MailBuilder builder = sender.compose().subject(getSubject(message, related));
|
||||
|
||||
for (String recipient : recipients) {
|
||||
builder.to(recipient);
|
||||
}
|
||||
|
||||
for (MetaAttachment attachment : messages.findAttachments(message)) {
|
||||
final Path filePath = MetaFiles.getPath(attachment.getMetaFile());
|
||||
final File file = filePath.toFile();
|
||||
builder.attach(file.getName(), file.toString());
|
||||
}
|
||||
|
||||
final MimeMessage email;
|
||||
try {
|
||||
builder.html(template(message, related));
|
||||
email = builder.build(message.getMessageId());
|
||||
final Set<String> references = new LinkedHashSet<>();
|
||||
if (message.getParent() != null) {
|
||||
references.add(message.getParent().getMessageId());
|
||||
}
|
||||
if (message.getRoot() != null) {
|
||||
references.add(message.getRoot().getMessageId());
|
||||
}
|
||||
if (!references.isEmpty()) {
|
||||
email.setHeader("References", Joiner.on(" ").skipNulls().join(references));
|
||||
}
|
||||
} catch (MessagingException | IOException e) {
|
||||
throw new MailException(e);
|
||||
}
|
||||
|
||||
// send email using a separate process to void thread blocking
|
||||
executor.submit(
|
||||
new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
send(sender, email);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private MailSender getMailSender(EmailAccount emailAccount) {
|
||||
|
||||
if (senderAccount == null
|
||||
|| !senderAccount.getId().equals(emailAccount.getId())
|
||||
|| !senderAccount.getVersion().equals(emailAccount.getVersion())) {
|
||||
senderAccount = emailAccount;
|
||||
sender = null;
|
||||
}
|
||||
|
||||
if (sender == null) {
|
||||
MailAccount mailAccount = mailAccountService.getMailAccount(emailAccount);
|
||||
sender = new MailSender(mailAccount);
|
||||
}
|
||||
|
||||
return sender;
|
||||
}
|
||||
|
||||
private MailReader getMailReader(EmailAccount emailAccount) {
|
||||
|
||||
if (readerAccount == null
|
||||
|| !readerAccount.getId().equals(emailAccount.getId())
|
||||
|| !readerAccount.getVersion().equals(emailAccount.getVersion())) {
|
||||
readerAccount = emailAccount;
|
||||
reader = null;
|
||||
}
|
||||
|
||||
if (reader == null) {
|
||||
MailAccount mailAccount = mailAccountService.getMailAccount(emailAccount);
|
||||
reader = new MailReader(mailAccount);
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.EmailAddress;
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.meta.db.MetaAttachment;
|
||||
import com.axelor.meta.db.MetaFile;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
public interface MessageService {
|
||||
|
||||
@Transactional
|
||||
public Message createMessage(
|
||||
String model,
|
||||
int id,
|
||||
String subject,
|
||||
String content,
|
||||
EmailAddress fromEmailAddress,
|
||||
List<EmailAddress> replytoEmailAddressList,
|
||||
List<EmailAddress> toEmailAddressList,
|
||||
List<EmailAddress> ccEmailAddressList,
|
||||
List<EmailAddress> bccEmailAddressList,
|
||||
Set<MetaFile> metaFiles,
|
||||
String addressBlock,
|
||||
int mediaTypeSelect,
|
||||
EmailAccount emailAccount);
|
||||
|
||||
@Transactional
|
||||
public void attachMetaFiles(Message message, Set<MetaFile> metaFiles);
|
||||
|
||||
public Set<MetaAttachment> getMetaAttachments(Message message);
|
||||
|
||||
public Message sendMessage(Message message) throws AxelorException;
|
||||
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Message sendByEmail(Message message) throws MessagingException, AxelorException;
|
||||
|
||||
@Transactional
|
||||
public Message sendToUser(Message message);
|
||||
|
||||
@Transactional
|
||||
public Message sendByMail(Message message);
|
||||
|
||||
public String printMessage(Message message) throws AxelorException;
|
||||
|
||||
/**
|
||||
* Regenerate message with template attached it.
|
||||
*
|
||||
* @param message Message to regenerate.
|
||||
* @return The new message regenerated.
|
||||
* @throws Exception If a error append during generation.
|
||||
*/
|
||||
Message regenerateMessage(Message message) throws Exception;
|
||||
|
||||
public String getFullEmailAddress(EmailAddress emailAddress);
|
||||
}
|
||||
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.EmailAddress;
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.repo.EmailAccountRepository;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.auth.AuthUtils;
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.db.JpaSupport;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.mail.MailBuilder;
|
||||
import com.axelor.mail.MailSender;
|
||||
import com.axelor.mail.SmtpAccount;
|
||||
import com.axelor.meta.MetaFiles;
|
||||
import com.axelor.meta.db.MetaAttachment;
|
||||
import com.axelor.meta.db.MetaFile;
|
||||
import com.axelor.meta.db.repo.MetaAttachmentRepository;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import javax.mail.MessagingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MessageServiceImpl extends JpaSupport implements MessageService {
|
||||
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private MetaAttachmentRepository metaAttachmentRepository;
|
||||
protected MessageRepository messageRepository;
|
||||
|
||||
private ExecutorService executor = Executors.newCachedThreadPool();
|
||||
private static final int ENTITY_FIND_TIMEOUT = 10000;
|
||||
private static final int ENTITY_FIND_INTERVAL = 200;
|
||||
|
||||
@Inject
|
||||
public MessageServiceImpl(
|
||||
MetaAttachmentRepository metaAttachmentRepository, MessageRepository messageRepository) {
|
||||
this.metaAttachmentRepository = metaAttachmentRepository;
|
||||
this.messageRepository = messageRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Message createMessage(
|
||||
String model,
|
||||
int id,
|
||||
String subject,
|
||||
String content,
|
||||
EmailAddress fromEmailAddress,
|
||||
List<EmailAddress> replyToEmailAddressList,
|
||||
List<EmailAddress> toEmailAddressList,
|
||||
List<EmailAddress> ccEmailAddressList,
|
||||
List<EmailAddress> bccEmailAddressList,
|
||||
Set<MetaFile> metaFiles,
|
||||
String addressBlock,
|
||||
int mediaTypeSelect,
|
||||
EmailAccount emailAccount) {
|
||||
|
||||
emailAccount =
|
||||
emailAccount != null
|
||||
? Beans.get(EmailAccountRepository.class).find(emailAccount.getId())
|
||||
: emailAccount;
|
||||
Message message =
|
||||
createMessage(
|
||||
content,
|
||||
fromEmailAddress,
|
||||
model,
|
||||
id,
|
||||
null,
|
||||
0,
|
||||
false,
|
||||
MessageRepository.STATUS_DRAFT,
|
||||
subject,
|
||||
MessageRepository.TYPE_SENT,
|
||||
replyToEmailAddressList,
|
||||
toEmailAddressList,
|
||||
ccEmailAddressList,
|
||||
bccEmailAddressList,
|
||||
addressBlock,
|
||||
mediaTypeSelect,
|
||||
emailAccount);
|
||||
|
||||
messageRepository.save(message);
|
||||
|
||||
attachMetaFiles(message, metaFiles);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void attachMetaFiles(Message message, Set<MetaFile> metaFiles) {
|
||||
|
||||
Preconditions.checkNotNull(message.getId());
|
||||
|
||||
if (metaFiles == null || metaFiles.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Add metafiles to object {}:{}", Message.class.getName(), message.getId());
|
||||
|
||||
for (MetaFile metaFile : metaFiles) {
|
||||
Beans.get(MetaFiles.class).attach(metaFile, metaFile.getFileName(), message);
|
||||
}
|
||||
}
|
||||
|
||||
protected Message createMessage(
|
||||
String content,
|
||||
EmailAddress fromEmailAddress,
|
||||
String relatedTo1Select,
|
||||
long relatedTo1SelectId,
|
||||
String relatedTo2Select,
|
||||
long relatedTo2SelectId,
|
||||
boolean sentByEmail,
|
||||
int statusSelect,
|
||||
String subject,
|
||||
int typeSelect,
|
||||
List<EmailAddress> replyToEmailAddressList,
|
||||
List<EmailAddress> toEmailAddressList,
|
||||
List<EmailAddress> ccEmailAddressList,
|
||||
List<EmailAddress> bccEmailAddressList,
|
||||
String addressBlock,
|
||||
int mediaTypeSelect,
|
||||
EmailAccount emailAccount) {
|
||||
|
||||
Set<EmailAddress> replyToEmailAddressSet = Sets.newHashSet();
|
||||
Set<EmailAddress> bccEmailAddressSet = Sets.newHashSet();
|
||||
Set<EmailAddress> toEmailAddressSet = Sets.newHashSet();
|
||||
Set<EmailAddress> ccEmailAddressSet = Sets.newHashSet();
|
||||
|
||||
if (mediaTypeSelect == MessageRepository.MEDIA_TYPE_EMAIL) {
|
||||
if (replyToEmailAddressList != null) {
|
||||
replyToEmailAddressSet.addAll(replyToEmailAddressList);
|
||||
}
|
||||
if (bccEmailAddressList != null) {
|
||||
bccEmailAddressSet.addAll(bccEmailAddressList);
|
||||
}
|
||||
if (toEmailAddressList != null) {
|
||||
toEmailAddressSet.addAll(toEmailAddressList);
|
||||
}
|
||||
if (ccEmailAddressList != null) {
|
||||
ccEmailAddressSet.addAll(ccEmailAddressList);
|
||||
}
|
||||
}
|
||||
|
||||
if (emailAccount != null) {
|
||||
content += "<p></p><p></p>" + Beans.get(MailAccountService.class).getSignature(emailAccount);
|
||||
}
|
||||
|
||||
Message message =
|
||||
new Message(
|
||||
typeSelect,
|
||||
subject,
|
||||
content,
|
||||
statusSelect,
|
||||
mediaTypeSelect,
|
||||
addressBlock,
|
||||
fromEmailAddress,
|
||||
replyToEmailAddressSet,
|
||||
toEmailAddressSet,
|
||||
ccEmailAddressSet,
|
||||
bccEmailAddressSet,
|
||||
sentByEmail,
|
||||
emailAccount);
|
||||
|
||||
message.setRelatedTo1Select(relatedTo1Select);
|
||||
message.setRelatedTo1SelectId(relatedTo1SelectId);
|
||||
message.setRelatedTo2Select(relatedTo2Select);
|
||||
message.setRelatedTo2SelectId(relatedTo2SelectId);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public Message sendMessage(Message message) throws AxelorException {
|
||||
try {
|
||||
message.setStatusSelect(MessageRepository.STATUS_IN_PROGRESS);
|
||||
if (message.getMediaTypeSelect() == MessageRepository.MEDIA_TYPE_MAIL) {
|
||||
return sendByMail(message);
|
||||
} else if (message.getMediaTypeSelect() == MessageRepository.MEDIA_TYPE_EMAIL) {
|
||||
return sendByEmail(message);
|
||||
} else if (message.getMediaTypeSelect() == MessageRepository.MEDIA_TYPE_CHAT) {
|
||||
return sendToUser(message);
|
||||
}
|
||||
} catch (MessagingException e) {
|
||||
TraceBackService.trace(e);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Message sendToUser(Message message) {
|
||||
|
||||
if (message.getRecipientUser() == null) {
|
||||
return message;
|
||||
}
|
||||
|
||||
message.setSenderUser(AuthUtils.getUser());
|
||||
log.debug("Sent internal message to user ::: {}", message.getRecipientUser());
|
||||
|
||||
message.setStatusSelect(MessageRepository.STATUS_SENT);
|
||||
message.setSentByEmail(false);
|
||||
message.setSentDateT(LocalDateTime.now());
|
||||
return messageRepository.save(message);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Message sendByMail(Message message) {
|
||||
|
||||
log.debug("Sent mail");
|
||||
message.setStatusSelect(MessageRepository.STATUS_SENT);
|
||||
message.setSentByEmail(false);
|
||||
message.setSentDateT(LocalDateTime.now());
|
||||
return messageRepository.save(message);
|
||||
}
|
||||
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Message sendByEmail(Message message) throws MessagingException, AxelorException {
|
||||
|
||||
EmailAccount mailAccount = message.getMailAccount();
|
||||
|
||||
if (mailAccount == null) {
|
||||
return message;
|
||||
}
|
||||
|
||||
log.debug("Sent email");
|
||||
MailAccountService mailAccountService = Beans.get(MailAccountService.class);
|
||||
com.axelor.mail.MailAccount account =
|
||||
new SmtpAccount(
|
||||
mailAccount.getHost(),
|
||||
mailAccount.getPort().toString(),
|
||||
mailAccount.getLogin(),
|
||||
mailAccountService.getDecryptPassword(mailAccount.getPassword()),
|
||||
mailAccountService.getSecurity(mailAccount));
|
||||
|
||||
List<String> replytoRecipients = this.getEmailAddresses(message.getReplyToEmailAddressSet());
|
||||
List<String> toRecipients = this.getEmailAddresses(message.getToEmailAddressSet());
|
||||
List<String> ccRecipients = this.getEmailAddresses(message.getCcEmailAddressSet());
|
||||
List<String> bccRecipients = this.getEmailAddresses(message.getBccEmailAddressSet());
|
||||
|
||||
if (toRecipients.isEmpty() && ccRecipients.isEmpty() && bccRecipients.isEmpty()) {
|
||||
throw new AxelorException(
|
||||
message,
|
||||
TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
|
||||
I18n.get(IExceptionMessage.MESSAGE_6));
|
||||
}
|
||||
|
||||
MailSender sender = new MailSender(account);
|
||||
MailBuilder mailBuilder = sender.compose();
|
||||
|
||||
mailBuilder.subject(message.getSubject());
|
||||
|
||||
if (message.getFromEmailAddress() != null) {
|
||||
if (!Strings.isNullOrEmpty(message.getFromEmailAddress().getAddress())) {
|
||||
log.debug("Override from ::: {}", this.getFullEmailAddress(message.getFromEmailAddress()));
|
||||
mailBuilder.from(this.getFullEmailAddress(message.getFromEmailAddress()));
|
||||
} else {
|
||||
throw new AxelorException(
|
||||
message, TraceBackRepository.CATEGORY_CONFIGURATION_ERROR, IExceptionMessage.MESSAGE_5);
|
||||
}
|
||||
}
|
||||
if (replytoRecipients != null && !replytoRecipients.isEmpty()) {
|
||||
mailBuilder.replyTo(Joiner.on(",").join(replytoRecipients));
|
||||
}
|
||||
if (toRecipients != null && !toRecipients.isEmpty()) {
|
||||
mailBuilder.to(Joiner.on(",").join(toRecipients));
|
||||
}
|
||||
if (ccRecipients != null && !ccRecipients.isEmpty()) {
|
||||
mailBuilder.cc(Joiner.on(",").join(ccRecipients));
|
||||
}
|
||||
if (bccRecipients != null && !bccRecipients.isEmpty()) {
|
||||
mailBuilder.bcc(Joiner.on(",").join(bccRecipients));
|
||||
}
|
||||
if (!Strings.isNullOrEmpty(message.getContent())) {
|
||||
mailBuilder.html(message.getContent());
|
||||
}
|
||||
|
||||
for (MetaAttachment metaAttachment : getMetaAttachments(message)) {
|
||||
MetaFile metaFile = metaAttachment.getMetaFile();
|
||||
mailBuilder.attach(metaFile.getFileName(), MetaFiles.getPath(metaFile).toString());
|
||||
}
|
||||
|
||||
getEntityManager().flush();
|
||||
|
||||
// send email using a separate process to avoid thread blocking
|
||||
executor.submit(
|
||||
() -> {
|
||||
try {
|
||||
final Message updateMessage = findMessage(message);
|
||||
mailBuilder.send();
|
||||
inTransaction(
|
||||
() -> {
|
||||
updateMessage.setSentByEmail(true);
|
||||
updateMessage.setStatusSelect(MessageRepository.STATUS_SENT);
|
||||
updateMessage.setSentDateT(LocalDateTime.now());
|
||||
updateMessage.setSenderUser(AuthUtils.getUser());
|
||||
messageRepository.save(updateMessage);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(e);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
private Message findMessage(Message message) throws InterruptedException, TimeoutException {
|
||||
Message foundMessage;
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
||||
while ((foundMessage = messageRepository.find(message.getId())) == null) {
|
||||
if (System.currentTimeMillis() - startTime > ENTITY_FIND_TIMEOUT) {
|
||||
throw new TimeoutException(String.format("Cannot find message: %s", message));
|
||||
}
|
||||
Thread.sleep(ENTITY_FIND_INTERVAL);
|
||||
}
|
||||
|
||||
return foundMessage;
|
||||
}
|
||||
|
||||
public Set<MetaAttachment> getMetaAttachments(Message message) {
|
||||
|
||||
Query<MetaAttachment> query =
|
||||
metaAttachmentRepository
|
||||
.all()
|
||||
.filter(
|
||||
"self.objectId = ?1 AND self.objectName = ?2",
|
||||
message.getId(),
|
||||
Message.class.getName());
|
||||
return Sets.newHashSet(query.fetch());
|
||||
}
|
||||
|
||||
public List<String> getEmailAddresses(Set<EmailAddress> emailAddressSet) {
|
||||
|
||||
List<String> recipients = Lists.newArrayList();
|
||||
if (emailAddressSet != null) {
|
||||
for (EmailAddress emailAddress : emailAddressSet) {
|
||||
|
||||
if (Strings.isNullOrEmpty(emailAddress.getAddress())) {
|
||||
continue;
|
||||
}
|
||||
recipients.add(this.getFullEmailAddress(emailAddress));
|
||||
}
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String printMessage(Message message) throws AxelorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Message regenerateMessage(Message message) throws Exception {
|
||||
Preconditions.checkNotNull(
|
||||
message.getTemplate(),
|
||||
I18n.get("Cannot regenerate message without template associated to message."));
|
||||
Preconditions.checkNotNull(
|
||||
message.getRelatedTo1Select(),
|
||||
I18n.get("Cannot regenerate message without related model."));
|
||||
Class m = Class.forName(message.getRelatedTo1Select());
|
||||
Model model = JPA.all(m).filter("self.id = ?", message.getRelatedTo1SelectId()).fetchOne();
|
||||
Message newMessage =
|
||||
Beans.get(TemplateMessageService.class).generateMessage(model, message.getTemplate());
|
||||
newMessage.setRelatedTo2Select(message.getRelatedTo2Select());
|
||||
newMessage.setRelatedTo2SelectId(message.getRelatedTo2SelectId());
|
||||
message.setArchived(true);
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullEmailAddress(EmailAddress emailAddress) {
|
||||
return emailAddress.getAddress();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.TemplateContext;
|
||||
import com.axelor.rpc.Context;
|
||||
import com.axelor.script.GroovyScriptHelper;
|
||||
import com.axelor.script.ScriptHelper;
|
||||
|
||||
public class TemplateContextService {
|
||||
|
||||
public Object computeTemplateContext(String groovyScript, Context values) {
|
||||
|
||||
ScriptHelper scriptHelper = new GroovyScriptHelper(values);
|
||||
|
||||
return scriptHelper.eval(groovyScript);
|
||||
}
|
||||
|
||||
public Object computeTemplateContext(TemplateContext templateContext, Context values) {
|
||||
return this.computeTemplateContext(templateContext.getValue(), values);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.Template;
|
||||
import com.axelor.auth.db.User;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.meta.db.MetaFile;
|
||||
import com.axelor.tool.template.TemplateMaker;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
public interface TemplateMessageService {
|
||||
|
||||
public Message generateMessage(Model model, Template template)
|
||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
|
||||
AxelorException, IOException;
|
||||
|
||||
public Message generateMessage(Long objectId, String model, String tag, Template template)
|
||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
|
||||
AxelorException, IOException;
|
||||
|
||||
public Message generateAndSendMessage(Model model, Template template)
|
||||
throws MessagingException, IOException, AxelorException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException;
|
||||
|
||||
public Message generateAndSendMessageToBulkUsers(Model model, Template template, Set<User> users)
|
||||
throws MessagingException, IOException, AxelorException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException;
|
||||
|
||||
public Set<MetaFile> getMetaFiles(Template template) throws AxelorException, IOException;
|
||||
|
||||
public TemplateMaker initMaker(long objectId, String model, String tag, boolean isJson)
|
||||
throws InstantiationException, IllegalAccessException, ClassNotFoundException;
|
||||
}
|
||||
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.EmailAddress;
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.Template;
|
||||
import com.axelor.apps.message.db.TemplateContext;
|
||||
import com.axelor.apps.message.db.repo.EmailAccountRepository;
|
||||
import com.axelor.apps.message.db.repo.EmailAddressRepository;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.db.repo.TemplateRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.auth.db.User;
|
||||
import com.axelor.db.EntityHelper;
|
||||
import com.axelor.db.JPA;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.dms.db.DMSFile;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.db.MetaFile;
|
||||
import com.axelor.meta.db.MetaJsonModel;
|
||||
import com.axelor.meta.db.MetaJsonRecord;
|
||||
import com.axelor.meta.db.MetaModel;
|
||||
import com.axelor.rpc.Context;
|
||||
import com.axelor.tool.template.TemplateMaker;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.persist.Transactional;
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.mail.MessagingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TemplateMessageServiceImpl implements TemplateMessageService {
|
||||
|
||||
private static final String RECIPIENT_SEPARATOR = ";|,";
|
||||
private static final char TEMPLATE_DELIMITER = '$';
|
||||
@Inject protected EmailAccountRepository mailAccountRepo;
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
protected TemplateMaker maker =
|
||||
new TemplateMaker(Locale.FRENCH, TEMPLATE_DELIMITER, TEMPLATE_DELIMITER);
|
||||
|
||||
protected MessageService messageService;
|
||||
protected TemplateContextService templateContextService;
|
||||
|
||||
@Inject
|
||||
public TemplateMessageServiceImpl(
|
||||
MessageService messageService, TemplateContextService templateContextService) {
|
||||
this.messageService = messageService;
|
||||
this.templateContextService = templateContextService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message generateMessage(Model model, Template template)
|
||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
|
||||
AxelorException, IOException {
|
||||
Class<?> klass = EntityHelper.getEntityClass(model);
|
||||
return generateMessage(
|
||||
model.getId(), klass.getCanonicalName(), klass.getSimpleName(), template);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackOn = {Exception.class})
|
||||
public Message generateMessage(Long objectId, String model, String tag, Template template)
|
||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
|
||||
AxelorException, IOException {
|
||||
|
||||
Object modelObj = template.getIsJson() ? template.getMetaJsonModel() : template.getMetaModel();
|
||||
|
||||
if (modelObj != null) {
|
||||
String modelName =
|
||||
template.getIsJson()
|
||||
? ((MetaJsonModel) modelObj).getName()
|
||||
: ((MetaModel) modelObj).getFullName();
|
||||
|
||||
if (!model.equals(modelName)) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||
String.format(
|
||||
I18n.get(IExceptionMessage.INVALID_MODEL_TEMPLATE_EMAIL), modelName, model));
|
||||
}
|
||||
initMaker(objectId, model, tag, template.getIsJson());
|
||||
computeTemplateContexts(
|
||||
template.getTemplateContextList(), objectId, model, template.getIsJson());
|
||||
}
|
||||
|
||||
log.debug("model : {}", model);
|
||||
log.debug("tag : {}", tag);
|
||||
log.debug("object id : {}", objectId);
|
||||
log.debug("template : {}", template);
|
||||
|
||||
String content = "";
|
||||
String subject = "";
|
||||
String from = "";
|
||||
String replyToRecipients = "";
|
||||
String toRecipients = "";
|
||||
String ccRecipients = "";
|
||||
String bccRecipients = "";
|
||||
String addressBlock = "";
|
||||
int mediaTypeSelect;
|
||||
|
||||
if (!Strings.isNullOrEmpty(template.getContent())) {
|
||||
// Set template
|
||||
maker.setTemplate(template.getContent());
|
||||
content = maker.make();
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(template.getAddressBlock())) {
|
||||
maker.setTemplate(template.getAddressBlock());
|
||||
// Make it
|
||||
addressBlock = maker.make();
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(template.getSubject())) {
|
||||
maker.setTemplate(template.getSubject());
|
||||
subject = maker.make();
|
||||
log.debug("Subject ::: {}", subject);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(template.getFromAdress())) {
|
||||
maker.setTemplate(template.getFromAdress());
|
||||
from = maker.make();
|
||||
log.debug("From ::: {}", from);
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(template.getReplyToRecipients())) {
|
||||
maker.setTemplate(template.getReplyToRecipients());
|
||||
replyToRecipients = maker.make();
|
||||
log.debug("Reply to ::: {}", replyToRecipients);
|
||||
}
|
||||
|
||||
if (template.getToRecipients() != null) {
|
||||
maker.setTemplate(template.getToRecipients());
|
||||
toRecipients = maker.make();
|
||||
log.debug("To ::: {}", toRecipients);
|
||||
}
|
||||
|
||||
if (template.getCcRecipients() != null) {
|
||||
maker.setTemplate(template.getCcRecipients());
|
||||
ccRecipients = maker.make();
|
||||
log.debug("CC ::: {}", ccRecipients);
|
||||
}
|
||||
|
||||
if (template.getBccRecipients() != null) {
|
||||
maker.setTemplate(template.getBccRecipients());
|
||||
bccRecipients = maker.make();
|
||||
log.debug("BCC ::: {}", bccRecipients);
|
||||
}
|
||||
|
||||
mediaTypeSelect = this.getMediaTypeSelect(template);
|
||||
log.debug("Media ::: {}", mediaTypeSelect);
|
||||
log.debug("Content ::: {}", content);
|
||||
|
||||
Message message =
|
||||
messageService.createMessage(
|
||||
model,
|
||||
Math.toIntExact(objectId),
|
||||
subject,
|
||||
content,
|
||||
getEmailAddress(from),
|
||||
getEmailAddresses(replyToRecipients),
|
||||
getEmailAddresses(toRecipients),
|
||||
getEmailAddresses(ccRecipients),
|
||||
getEmailAddresses(bccRecipients),
|
||||
null,
|
||||
addressBlock,
|
||||
mediaTypeSelect,
|
||||
getMailAccount());
|
||||
|
||||
message.setTemplate(Beans.get(TemplateRepository.class).find(template.getId()));
|
||||
|
||||
// Save message if it's not related to the USER model
|
||||
if (!"com.axelor.auth.db.User".equals(model)) {
|
||||
message = Beans.get(MessageRepository.class).save(message);
|
||||
}
|
||||
|
||||
messageService.attachMetaFiles(message, getMetaFiles(template));
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message generateAndSendMessage(Model model, Template template)
|
||||
throws MessagingException, IOException, AxelorException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException {
|
||||
|
||||
Message message = this.generateMessage(model, template);
|
||||
messageService.sendMessage(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message generateAndSendMessageToBulkUsers(Model model, Template template, Set<User> users)
|
||||
throws MessagingException, IOException, AxelorException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException {
|
||||
|
||||
Message message = this.generateMessage(model, template);
|
||||
Set<EmailAddress> emailAddresses = new HashSet<>();
|
||||
for (User user : users) {
|
||||
emailAddresses.add(getEmailAddress(user.getEmail()));
|
||||
}
|
||||
|
||||
// Set recipients as sets
|
||||
message.setToEmailAddressSet(emailAddresses);
|
||||
message.setCcEmailAddressSet(emailAddresses);
|
||||
|
||||
messageService.sendMessage(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MetaFile> getMetaFiles(Template template) throws AxelorException, IOException {
|
||||
|
||||
List<DMSFile> metaAttachments =
|
||||
Query.of(DMSFile.class)
|
||||
.filter(
|
||||
"self.relatedId = ?1 AND self.relatedModel = ?2",
|
||||
template.getId(),
|
||||
EntityHelper.getEntityClass(template).getName())
|
||||
.fetch();
|
||||
Set<MetaFile> metaFiles = Sets.newHashSet();
|
||||
for (DMSFile metaAttachment : metaAttachments) {
|
||||
if (!metaAttachment.getIsDirectory()) metaFiles.add(metaAttachment.getMetaFile());
|
||||
}
|
||||
|
||||
log.debug("Metafile to attach: {}", metaFiles);
|
||||
return metaFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public TemplateMaker initMaker(long objectId, String model, String tag, boolean isJson)
|
||||
throws ClassNotFoundException {
|
||||
|
||||
if (isJson) {
|
||||
maker.setContext(JPA.find(MetaJsonRecord.class, objectId), tag);
|
||||
} else {
|
||||
Class<? extends Model> myClass = (Class<? extends Model>) Class.forName(model);
|
||||
maker.setContext(JPA.find(myClass, objectId), tag);
|
||||
}
|
||||
|
||||
return maker;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected TemplateMaker computeTemplateContexts(
|
||||
List<TemplateContext> templateContextList, long objectId, String model, boolean isJson)
|
||||
throws ClassNotFoundException {
|
||||
|
||||
if (templateContextList == null) {
|
||||
return maker;
|
||||
}
|
||||
|
||||
Context context = null;
|
||||
if (isJson) {
|
||||
context = new com.axelor.rpc.Context(objectId, MetaJsonRecord.class);
|
||||
} else {
|
||||
Class<? extends Model> myClass = (Class<? extends Model>) Class.forName(model);
|
||||
context = new com.axelor.rpc.Context(objectId, myClass);
|
||||
}
|
||||
|
||||
for (TemplateContext templateContext : templateContextList) {
|
||||
Object result = templateContextService.computeTemplateContext(templateContext, context);
|
||||
maker.addContext(templateContext.getName(), result);
|
||||
}
|
||||
|
||||
return maker;
|
||||
}
|
||||
|
||||
protected List<EmailAddress> getEmailAddresses(String recipients) {
|
||||
|
||||
List<EmailAddress> emailAddressList = Lists.newArrayList();
|
||||
if (Strings.isNullOrEmpty(recipients)) {
|
||||
return emailAddressList;
|
||||
}
|
||||
|
||||
for (String recipient :
|
||||
Splitter.onPattern(RECIPIENT_SEPARATOR)
|
||||
.trimResults()
|
||||
.omitEmptyStrings()
|
||||
.splitToList(recipients)) {
|
||||
emailAddressList.add(getEmailAddress(recipient));
|
||||
}
|
||||
return emailAddressList;
|
||||
}
|
||||
|
||||
protected EmailAddress getEmailAddress(String recipient) {
|
||||
|
||||
if (Strings.isNullOrEmpty(recipient)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EmailAddressRepository emailAddressRepo = Beans.get(EmailAddressRepository.class);
|
||||
|
||||
EmailAddress emailAddress = emailAddressRepo.findByAddress(recipient);
|
||||
|
||||
if (emailAddress == null) {
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("address", recipient);
|
||||
emailAddress = emailAddressRepo.create(values);
|
||||
}
|
||||
|
||||
return emailAddress;
|
||||
}
|
||||
|
||||
protected Integer getMediaTypeSelect(Template template) {
|
||||
|
||||
return template.getMediaTypeSelect();
|
||||
}
|
||||
|
||||
protected EmailAccount getMailAccount() {
|
||||
|
||||
EmailAccount mailAccount = Beans.get(MailAccountService.class).getDefaultSender();
|
||||
|
||||
if (mailAccount != null) {
|
||||
log.debug("Email account ::: {}", mailAccount);
|
||||
return mailAccount;
|
||||
}
|
||||
|
||||
System.out.println("getMailAccount");
|
||||
// EmailAccount mailAccount = Beans.get(MailAccountService.class).getDefaultSender();
|
||||
EmailAccount mail = getDefaultSender();
|
||||
|
||||
// if (mailAccount != null) {
|
||||
// log.debug("Email account ::: {}", mailAccount);
|
||||
// return mailAccount;
|
||||
// }
|
||||
if (mail != null) {
|
||||
log.debug("Email ::: {}", mail);
|
||||
return mail;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected EmailAccount getDefaultSender() {
|
||||
EmailAccount mail =
|
||||
mailAccountRepo
|
||||
.all()
|
||||
.filter(
|
||||
"self.isDefault = true AND self.serverTypeSelect = ?1",
|
||||
EmailAccountRepository.SERVER_TYPE_SMTP)
|
||||
.fetchOne();
|
||||
if (mail != null) {
|
||||
log.debug("Email ::: {}", mail);
|
||||
return mail;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.service;
|
||||
|
||||
import com.axelor.apps.message.db.Template;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.db.mapper.Mapper;
|
||||
import com.axelor.db.mapper.Property;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.meta.db.MetaModel;
|
||||
import com.axelor.tool.template.TemplateMaker;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@Singleton
|
||||
public class TemplateService {
|
||||
|
||||
public void checkTargetReceptor(Template template) throws AxelorException {
|
||||
String target = template.getTarget();
|
||||
MetaModel metaModel = template.getMetaModel();
|
||||
|
||||
if (Strings.isNullOrEmpty(target)) {
|
||||
return;
|
||||
}
|
||||
if (metaModel == null) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.TEMPLATE_SERVICE_1));
|
||||
}
|
||||
|
||||
try {
|
||||
this.validTarget(target, metaModel);
|
||||
} catch (Exception e) {
|
||||
throw new AxelorException(
|
||||
e.getCause(),
|
||||
TraceBackRepository.CATEGORY_INCONSISTENCY,
|
||||
I18n.get(IExceptionMessage.TEMPLATE_SERVICE_2));
|
||||
}
|
||||
}
|
||||
|
||||
private void validTarget(String target, MetaModel metaModel) throws ClassNotFoundException {
|
||||
Iterator<String> iter = Splitter.on(".").split(target).iterator();
|
||||
Property p = Mapper.of(Class.forName(metaModel.getFullName())).getProperty(iter.next());
|
||||
while (iter.hasNext() && p != null) {
|
||||
p = Mapper.of(p.getTarget()).getProperty(iter.next());
|
||||
}
|
||||
|
||||
if (p == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public String processSubject(
|
||||
Template template, Model bean, String beanName, Map<String, Object> context) {
|
||||
TemplateMaker maker = new TemplateMaker(new Locale("fr"), '$', '$');
|
||||
|
||||
maker.setTemplate(template.getSubject());
|
||||
maker.setContext(bean, context, beanName);
|
||||
return maker.make();
|
||||
}
|
||||
|
||||
public String processContent(
|
||||
Template template, Model bean, String beanName, Map<String, Object> context) {
|
||||
TemplateMaker maker = new TemplateMaker(new Locale("fr"), '$', '$');
|
||||
|
||||
maker.setTemplate(template.getContent());
|
||||
maker.setContext(bean, context, beanName);
|
||||
return maker.make();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.web;
|
||||
|
||||
import com.axelor.apps.base.db.Wizard;
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.Template;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.db.repo.TemplateRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.apps.message.service.MessageService;
|
||||
import com.axelor.apps.message.service.TemplateMessageService;
|
||||
import com.axelor.db.Model;
|
||||
import com.axelor.db.Query;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.meta.schema.actions.ActionView;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.axelor.rpc.Context;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class GenerateMessageController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
public void callMessageWizard(ActionRequest request, ActionResponse response) {
|
||||
|
||||
Model context = request.getContext().asType(Model.class);
|
||||
String model = request.getModel();
|
||||
|
||||
LOG.debug("Call message wizard for model : {} ", model);
|
||||
|
||||
String[] decomposeModel = model.split("\\.");
|
||||
String simpleModel = decomposeModel[decomposeModel.length - 1];
|
||||
Query<? extends Template> templateQuery =
|
||||
Beans.get(TemplateRepository.class)
|
||||
.all()
|
||||
.filter("self.metaModel.fullName = ?1 AND self.isSystem != true", model);
|
||||
|
||||
try {
|
||||
|
||||
long templateNumber = templateQuery.count();
|
||||
|
||||
LOG.debug("Template number : {} ", templateNumber);
|
||||
|
||||
if (templateNumber == 0) {
|
||||
|
||||
response.setView(
|
||||
ActionView.define(I18n.get(IExceptionMessage.MESSAGE_3))
|
||||
.model(Message.class.getName())
|
||||
.add("form", "message-form")
|
||||
.param("forceEdit", "true")
|
||||
.context("_mediaTypeSelect", MessageRepository.MEDIA_TYPE_EMAIL)
|
||||
.context("_templateContextModel", model)
|
||||
.context("_objectId", context.getId().toString())
|
||||
.map());
|
||||
|
||||
} else if (templateNumber > 1) {
|
||||
|
||||
response.setView(
|
||||
ActionView.define(I18n.get(IExceptionMessage.MESSAGE_2))
|
||||
.model(Wizard.class.getName())
|
||||
.add("form", "generate-message-wizard-form")
|
||||
.param("show-confirm", "false")
|
||||
.context("_objectId", context.getId().toString())
|
||||
.context("_templateContextModel", model)
|
||||
.context("_tag", simpleModel)
|
||||
.map());
|
||||
|
||||
} else {
|
||||
response.setView(
|
||||
generateMessage(context.getId(), model, simpleModel, templateQuery.fetchOne()));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void generateMessage(ActionRequest request, ActionResponse response) {
|
||||
|
||||
Context context = request.getContext();
|
||||
Map<?, ?> templateContext = (Map<?, ?>) context.get("_xTemplate");
|
||||
Template template = null;
|
||||
if (templateContext != null) {
|
||||
template =
|
||||
Beans.get(TemplateRepository.class)
|
||||
.find(Long.parseLong(templateContext.get("id").toString()));
|
||||
}
|
||||
|
||||
Long objectId = Long.parseLong(context.get("_objectId").toString());
|
||||
String model = (String) context.get("_templateContextModel");
|
||||
String tag = (String) context.get("_tag");
|
||||
|
||||
try {
|
||||
response.setView(generateMessage(objectId, model, tag, template));
|
||||
response.setCanClose(true);
|
||||
} catch (Exception e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> generateMessage(
|
||||
long objectId, String model, String tag, Template template)
|
||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException,
|
||||
AxelorException, IOException {
|
||||
|
||||
LOG.debug("template : {} ", template);
|
||||
LOG.debug("object id : {} ", objectId);
|
||||
LOG.debug("model : {} ", model);
|
||||
LOG.debug("tag : {} ", tag);
|
||||
Message message = null;
|
||||
if (template != null) {
|
||||
message =
|
||||
Beans.get(TemplateMessageService.class).generateMessage(objectId, model, tag, template);
|
||||
} else {
|
||||
message =
|
||||
Beans.get(MessageService.class)
|
||||
.createMessage(
|
||||
model,
|
||||
Math.toIntExact(objectId),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
MessageRepository.MEDIA_TYPE_EMAIL,
|
||||
null);
|
||||
}
|
||||
|
||||
return ActionView.define(I18n.get(IExceptionMessage.MESSAGE_3))
|
||||
.model(Message.class.getName())
|
||||
.add("form", "message-form")
|
||||
.param("forceEdit", "true")
|
||||
.context("_showRecord", message.getId().toString())
|
||||
.map();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.web;
|
||||
|
||||
import com.axelor.apps.message.db.EmailAccount;
|
||||
import com.axelor.apps.message.db.repo.EmailAccountRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.apps.message.service.MailAccountService;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
@Singleton
|
||||
public class MailAccountController {
|
||||
|
||||
public void validateSmtpAccount(ActionRequest request, ActionResponse response) {
|
||||
|
||||
EmailAccount account = request.getContext().asType(EmailAccount.class);
|
||||
|
||||
try {
|
||||
|
||||
Beans.get(MailAccountService.class).checkMailAccountConfiguration(account);
|
||||
|
||||
response.setValue("isValid", Boolean.TRUE);
|
||||
response.setFlash(I18n.get(IExceptionMessage.MAIL_ACCOUNT_3));
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
TraceBackService.trace(response, e);
|
||||
response.setValue("isValid", Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkDefaultMailAccount(ActionRequest request, ActionResponse response)
|
||||
throws AxelorException {
|
||||
|
||||
EmailAccount account = request.getContext().asType(EmailAccount.class);
|
||||
try {
|
||||
Beans.get(MailAccountService.class).checkDefaultMailAccount(account);
|
||||
} catch (AxelorException e) {
|
||||
response.setAttr("isDefault", "value", false);
|
||||
response.setFlash(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchEmails(ActionRequest request, ActionResponse response)
|
||||
throws MessagingException, IOException {
|
||||
|
||||
EmailAccount account = request.getContext().asType(EmailAccount.class);
|
||||
account = Beans.get(EmailAccountRepository.class).find(account.getId());
|
||||
|
||||
int totalFetched = Beans.get(MailAccountService.class).fetchEmails(account, true);
|
||||
|
||||
response.setFlash(I18n.get(String.format("Total email fetched: %s", totalFetched)));
|
||||
}
|
||||
|
||||
public void validate(ActionRequest request, ActionResponse response) {
|
||||
if (request.getContext().get("newPassword") != null)
|
||||
response.setValue(
|
||||
"password",
|
||||
Beans.get(MailAccountService.class)
|
||||
.getEncryptPassword(request.getContext().get("newPassword").toString()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.web;
|
||||
|
||||
import com.axelor.apps.message.db.Message;
|
||||
import com.axelor.apps.message.db.repo.MessageRepository;
|
||||
import com.axelor.apps.message.exception.IExceptionMessage;
|
||||
import com.axelor.apps.message.service.MessageService;
|
||||
import com.axelor.apps.tool.ModelTool;
|
||||
import com.axelor.exception.AxelorException;
|
||||
import com.axelor.exception.db.repo.TraceBackRepository;
|
||||
import com.axelor.exception.service.TraceBackService;
|
||||
import com.axelor.i18n.I18n;
|
||||
import com.axelor.inject.Beans;
|
||||
import com.axelor.rpc.ActionRequest;
|
||||
import com.axelor.rpc.ActionResponse;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class MessageController {
|
||||
|
||||
public void sendMessage(ActionRequest request, ActionResponse response) {
|
||||
Message message = request.getContext().asType(Message.class);
|
||||
|
||||
try {
|
||||
Beans.get(MessageService.class)
|
||||
.sendMessage(Beans.get(MessageRepository.class).find(message.getId()));
|
||||
response.setReload(true);
|
||||
response.setFlash(I18n.get(IExceptionMessage.MESSAGE_4));
|
||||
} catch (AxelorException e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void sendMessages(ActionRequest request, ActionResponse response) {
|
||||
List<Integer> idList = (List<Integer>) request.getContext().get("_ids");
|
||||
try {
|
||||
if (idList == null) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.MESSAGE_MISSING_SELECTED_MESSAGES));
|
||||
}
|
||||
ModelTool.apply(
|
||||
Message.class,
|
||||
idList,
|
||||
model -> Beans.get(MessageService.class).sendMessage((Message) model));
|
||||
response.setFlash(
|
||||
String.format(I18n.get(IExceptionMessage.MESSAGES_SEND_IN_PROGRESS), idList.size()));
|
||||
response.setReload(true);
|
||||
} catch (AxelorException e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void regenerateMessages(ActionRequest request, ActionResponse response) {
|
||||
List<Integer> idList = (List<Integer>) request.getContext().get("_ids");
|
||||
try {
|
||||
if (idList == null) {
|
||||
throw new AxelorException(
|
||||
TraceBackRepository.CATEGORY_MISSING_FIELD,
|
||||
I18n.get(IExceptionMessage.MESSAGE_MISSING_SELECTED_MESSAGES));
|
||||
}
|
||||
int error =
|
||||
ModelTool.apply(
|
||||
Message.class,
|
||||
idList,
|
||||
model -> Beans.get(MessageService.class).regenerateMessage((Message) model));
|
||||
response.setFlash(
|
||||
String.format(
|
||||
I18n.get(IExceptionMessage.MESSAGES_REGENERATED), idList.size() - error, error));
|
||||
response.setReload(true);
|
||||
} catch (AxelorException e) {
|
||||
TraceBackService.trace(response, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<csv-inputs xmlns="http://axelor.com/xml/ns/data-import"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
|
||||
|
||||
<input file="auth_permission.csv" separator=";" type="com.axelor.auth.db.Permission" search="self.name = :name" call="com.axelor.csv.script.ImportPermission:importPermissionToRole">
|
||||
<bind to="canRead" eval="can_read == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canWrite" eval="can_write == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canCreate" eval="can_create == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canRemove" eval="can_remove == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canExport" eval="can_export == 'x' ? 'true' : 'false'"/>
|
||||
</input>
|
||||
|
||||
<input file="meta_metaMenu.csv" separator=";" type="com.axelor.meta.db.MetaMenu" search="self.name = :name" update="true"/>
|
||||
|
||||
<input file="meta_schedule.csv" separator=";" type="com.axelor.meta.db.MetaSchedule" />
|
||||
|
||||
</csv-inputs>
|
||||
@ -0,0 +1,2 @@
|
||||
"name";"object";"can_read";"can_write";"can_create";"can_remove";"can_export";"condition";"conditionParams";"roleName"
|
||||
"perm.message.all";"com.axelor.apps.message.db.*";"x";"x";"x";"x";"x";;;"Admin"
|
||||
|
@ -0,0 +1,9 @@
|
||||
"name";"roles.name"
|
||||
"mail-conf";"Admin"
|
||||
"mail-conf-template";"Admin"
|
||||
"mail-conf-template-rules";"Admin"
|
||||
"mail-root-email-conf-mail-account";"Admin"
|
||||
"mail-root-email-conf-email-address";"Admin"
|
||||
"mail-message";"Admin"
|
||||
"mail-message-not-send";"Admin"
|
||||
"mail-root-email-conf-routing";"Admin"
|
||||
|
@ -0,0 +1,2 @@
|
||||
active;name;job;cron
|
||||
false;Fetch emails on every 5 minutes ;com.axelor.apps.message.job.FetchEmailJob;0 0/5 * * * ?
|
||||
|
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="message" package="com.axelor.apps.message.db" />
|
||||
|
||||
<entity name="EmailAccount" lang="java">
|
||||
|
||||
<string name="name" title="Name" required="true" namecolumn="true" />
|
||||
<integer name="serverTypeSelect" title="Server Type" required="true" selection="mail.account.server.type.select" default="1"/>
|
||||
<string name="login" title="Login"/>
|
||||
<string name="password" title="Password" />
|
||||
<string name="host" title="Host" required="true"/>
|
||||
<integer name="port" title="Port" min="1" nullable="true"/>
|
||||
<integer name="securitySelect" title="SSL/STARTTLS" selection="mail.account.security.select"/>
|
||||
<boolean name="isDefault" title="Default account"/>
|
||||
<boolean name="isValid" title="Valid"/>
|
||||
<string name="signature" title="Signature" large="true"/>
|
||||
|
||||
<extra-code><![CDATA[
|
||||
|
||||
// SERVER TYPE SELECT
|
||||
public static final int SERVER_TYPE_SMTP = 1;
|
||||
public static final int SERVER_TYPE_POP = 2;
|
||||
public static final int SERVER_TYPE_IMAP = 3;
|
||||
|
||||
// SECURITY TYPE SELECT
|
||||
public static final int SECURITY_NONE = 0;
|
||||
public static final int SECURITY_SSL = 1;
|
||||
public static final int SECURITY_STARTTLS = 2;
|
||||
|
||||
]]></extra-code>
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="message" package="com.axelor.apps.message.db" />
|
||||
|
||||
<entity name="EmailAddress" lang="java">
|
||||
|
||||
<string name="address" title="Address" initParam="true" namecolumn="true" />
|
||||
<finder-method name="findByAddress" using="address" />
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="message" package="com.axelor.apps.message.db"/>
|
||||
|
||||
<entity name="Message" lang="java">
|
||||
|
||||
<integer name="typeSelect" title="Type" selection="message.type.select" readonly="true" default="2" initParam="true"/>
|
||||
<string name="subject" title="Subject" initParam="true" namecolumn="true"/>
|
||||
<string name="content" title="Content" large="true" initParam="true"/>
|
||||
<datetime name="sentDateT" title="Sent date" readonly="true"/>
|
||||
<date name="sendScheduleDate" title="Forecasted Sent Date" />
|
||||
<string name="relatedTo1Select" title="Related to" selection="message.related.to.select"/>
|
||||
<long name="relatedTo1SelectId"/>
|
||||
<string name="relatedTo2Select" title="Related to" selection="message.related.to.select"/>
|
||||
<long name="relatedTo2SelectId"/>
|
||||
<integer name="statusSelect" title="Status" selection="message.status.select" readonly="true" default="1" initParam="true"/>
|
||||
|
||||
<integer name="mediaTypeSelect" title="Media Type" selection="message.media.type.select" initParam="true"/>
|
||||
<string name="addressBlock" large="true" multiline="true" title="Address Block" initParam="true"/>
|
||||
|
||||
<!-- Email -->
|
||||
<many-to-one name="fromEmailAddress" ref="com.axelor.apps.message.db.EmailAddress" title="From" initParam="true"/>
|
||||
<many-to-many name="replyToEmailAddressSet" ref="com.axelor.apps.message.db.EmailAddress" title="Reply to" initParam="true" />
|
||||
<many-to-many name="toEmailAddressSet" ref="com.axelor.apps.message.db.EmailAddress" title="To" initParam="true"/>
|
||||
<many-to-many name="ccEmailAddressSet" ref="com.axelor.apps.message.db.EmailAddress" title="Cc" initParam="true"/>
|
||||
<many-to-many name="bccEmailAddressSet" ref="com.axelor.apps.message.db.EmailAddress" title="Bcc" initParam="true"/>
|
||||
<boolean name="sentByEmail" title="Sent by email" initParam="true"/>
|
||||
<many-to-one name="mailAccount" ref="com.axelor.apps.message.db.EmailAccount" title="Mail account" initParam="true"/>
|
||||
|
||||
<!-- Intern message -->
|
||||
<many-to-one name="senderUser" ref="com.axelor.auth.db.User" title="Sender (User)" readonly="true"/>
|
||||
<many-to-one name="recipientUser" ref="com.axelor.auth.db.User" title="Recipient"/>
|
||||
<many-to-one name="template" ref="com.axelor.apps.message.db.Template" readonly="true"/>
|
||||
|
||||
<finder-method name="findByRelatedTo"
|
||||
using="long:relatedToSelectId,String:relatedToSelect"
|
||||
filter="self.relatedTo1SelectId = :relatedToSelectId
|
||||
AND self.relatedTo1Select = :relatedToSelect
|
||||
OR self.relatedTo2SelectId = :relatedToSelectId
|
||||
AND self.relatedTo2Select = :relatedToSelect" all="true"/>
|
||||
|
||||
<extra-code><![CDATA[
|
||||
|
||||
// TYPE SELECT
|
||||
public static final int TYPE_RECEIVED = 1;
|
||||
public static final int TYPE_SENT = 2;
|
||||
|
||||
// STATUS SELECT
|
||||
public static final int STATUS_DRAFT = 1;
|
||||
public static final int STATUS_IN_PROGRESS = 2;
|
||||
public static final int STATUS_SENT = 3;
|
||||
public static final int STATUS_DELETED = 4;
|
||||
|
||||
// MEDIA TYPE SELECT
|
||||
public static final int MEDIA_TYPE_MAIL = 1;
|
||||
public static final int MEDIA_TYPE_EMAIL = 2;
|
||||
public static final int MEDIA_TYPE_CHAT = 3;
|
||||
|
||||
// RELATED TO SELECT
|
||||
public static final String RELATED_TO_PARTNER = "com.axelor.apps.base.db.Partner";
|
||||
public static final String RELATED_TO_LEAD = "com.axelor.apps.crm.db.Lead";
|
||||
public static final String RELATED_TO_OPPORTUNITY = "com.axelor.apps.crm.db.Opportunity";
|
||||
public static final String RELATED_TO_PRODUCT = "com.axelor.apps.base.db.Product";
|
||||
public static final String RELATED_TO_EVENT = "com.axelor.apps.crm.db.Event";
|
||||
public static final String RELATED_TO_SALESORDER = "com.axelor.apps.sale.db.SaleOrder";
|
||||
public static final String RELATED_TO_PROJECT = "com.axelor.apps.project.db.Project";
|
||||
|
||||
]]></extra-code>
|
||||
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="message" package="com.axelor.apps.message.db"/>
|
||||
|
||||
<entity name="Template" lang="java">
|
||||
|
||||
<string name="name" title="Name" required="true" namecolumn="true"/>
|
||||
<string name="content" large="true" multiline="true" title="Content"/>
|
||||
<string name="subject" large="true" multiline="true" title="Subject"/>
|
||||
<string name="fromAdress" large="true" multiline="true" title="From" />
|
||||
<string name="replyToRecipients" large="true" multiline="true" title="Reply to" />
|
||||
<string name="toRecipients" large="true" multiline="true" title="To"/>
|
||||
<string name="ccRecipients" large="true" multiline="true" title="Cc"/>
|
||||
<string name="bccRecipients" large="true" multiline="true" title="Bcc"/>
|
||||
<string name="target" title="Target receptor"/>
|
||||
<integer name="mediaTypeSelect" title="Media Type" required="true" selection="template.media.type.select" default="2"/>
|
||||
<string name="addressBlock" large="true" multiline="true" title="Address Block"/>
|
||||
<many-to-one name="metaModel" ref="com.axelor.meta.db.MetaModel" title="Model"/>
|
||||
<boolean name="isDefault" title="Default"/>
|
||||
<boolean name="isSystem" title="System"/>
|
||||
<boolean name="isJson" title="Json"/>
|
||||
<many-to-one name="metaJsonModel" ref="com.axelor.meta.db.MetaJsonModel" title="Model"/>
|
||||
|
||||
<one-to-many name="templateContextList" ref="com.axelor.apps.message.db.TemplateContext" mappedBy="template" title="Context"/>
|
||||
|
||||
|
||||
<extra-code><![CDATA[
|
||||
// MEDIA TYPE SELECT
|
||||
public static final int MEDIA_TYPE_MAIL = 1;
|
||||
public static final int MEDIA_TYPE_EMAIL = 2;
|
||||
public static final int MEDIA_TYPE_CHAT = 3;
|
||||
]]></extra-code>
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="base" package="com.axelor.apps.message.db"/>
|
||||
|
||||
<entity name="TemplateContext" lang="java">
|
||||
|
||||
<string name="name" title="Name"/>
|
||||
<string name="value" title="Expr. value" large="true"/>
|
||||
<many-to-one name="template" ref="com.axelor.apps.message.db.Template"/>
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
|
||||
|
||||
<module name="base" package="com.axelor.apps.base.db" />
|
||||
|
||||
<entity name="Wizard" lang="java">
|
||||
|
||||
<string name="name" title="Name" />
|
||||
<string name="code" title="Code" />
|
||||
<string name="recordId" title="Record Id" transient="true"/>
|
||||
<string name="recordName" title="Record Name" transient="true"/>
|
||||
|
||||
</entity>
|
||||
|
||||
</domain-models>
|
||||
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.",,,
|
||||
"Address",,,
|
||||
"Address Block",,,
|
||||
"All messages",,,
|
||||
"Bcc",,,
|
||||
"Cannot regenerate message without related model.",,,
|
||||
"Cannot regenerate message without template associated to message.",,,
|
||||
"Cc",,,
|
||||
"Chat",,,
|
||||
"Check Duplicate",,,
|
||||
"Code",,,
|
||||
"Configurations",,,
|
||||
"Connection successful",,,
|
||||
"Content",,,
|
||||
"Context",,,
|
||||
"Create message",,,
|
||||
"Default",,,
|
||||
"Default account",,,
|
||||
"Delete",,,
|
||||
"Deleted",,,
|
||||
"Draft",,,
|
||||
"Email",,,
|
||||
"Email Accounts",,,
|
||||
"Email address",,,
|
||||
"Email addresses",,,
|
||||
"Email sending is in progress",,,
|
||||
"Email sending is in progress for %d messages.",,,
|
||||
"Emails",,,
|
||||
"Expr. value",,,
|
||||
"Fetch emails",,,
|
||||
"Forecasted Sent Date",,,
|
||||
"From",,,
|
||||
"Generate message",,,
|
||||
"Group",,,
|
||||
"Host",,,
|
||||
"IMAP",,,
|
||||
"In progress",,,
|
||||
"Incorrect login or password",,,
|
||||
"Informations",,,
|
||||
"Json",,,
|
||||
"Language",,,
|
||||
"Login",,,
|
||||
"Mail",,,
|
||||
"Mail account",,,
|
||||
"Mail accounts",,,
|
||||
"Media Type",,,
|
||||
"Message",,,
|
||||
"Message destinated to",,,
|
||||
"Messages",,,
|
||||
"Messages not sent",,,
|
||||
"Model",,,
|
||||
"Model empty. Please configure a model.",,,
|
||||
"NONE",,,
|
||||
"Name",,,
|
||||
"No Mail content entered.",,,
|
||||
"POP",,,
|
||||
"Password",,,
|
||||
"Please configure a template",,,
|
||||
"Please select one or more messages.",,,
|
||||
"Please set the email template to send",,,
|
||||
"Port",,,
|
||||
"Print",,,
|
||||
"Provided settings are wrong, please modify them and try again",,,
|
||||
"Received",,,
|
||||
"Recipient",,,
|
||||
"Recipient address",,,
|
||||
"Recipients",,,
|
||||
"Record Id",,,
|
||||
"Record Name",,,
|
||||
"Regenerate messages",,,
|
||||
"Related to",,,
|
||||
"Related to1 select",,,
|
||||
"Related to2 select",,,
|
||||
"Reply to",,,
|
||||
"Resend messages",,,
|
||||
"Routings",,,
|
||||
"SMTP",,,
|
||||
"SSL",,,
|
||||
"SSL/STARTTLS",,,
|
||||
"STARTTLS",,,
|
||||
"Select template",,,
|
||||
"Send",,,
|
||||
"Sender (User)",,,
|
||||
"Sender's email address is null or empty",,,
|
||||
"Sent",,,
|
||||
"Sent by email",,,
|
||||
"Sent date",,,
|
||||
"Server Type",,,
|
||||
"Signature",,,
|
||||
"Status",,,
|
||||
"Subject",,,
|
||||
"System",,,
|
||||
"TO/CC/BCC recipient's email address is empty",,,
|
||||
"Target receptor",,,
|
||||
"Template",,,
|
||||
"Template Context",,,
|
||||
"Template Rules",,,
|
||||
"Templates",,,
|
||||
"Test connection",,,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account",,,
|
||||
"To",,,
|
||||
"Type",,,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS",,,
|
||||
"User",,,
|
||||
"Valid",,,
|
||||
"Validate",,,
|
||||
"Waiting model: %s",,,
|
||||
"Your target receptor is not valid. Please check it.",,,
|
||||
"user@mydomain.com",,,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","%d Nachrichten wurden erfolgreich neu generiert und %d Fehler hinzugefügt.",,
|
||||
"Address","Adresse",,
|
||||
"Address Block","Adressblock",,
|
||||
"All messages","Alle Nachrichten",,
|
||||
"Bcc","Bcc",,
|
||||
"Cannot regenerate message without related model.","Die Nachricht kann ohne zugehöriges Modell nicht neu generiert werden.",,
|
||||
"Cannot regenerate message without template associated to message.","Die Nachricht kann nicht neu generiert werden, ohne dass der Nachricht eine Vorlage zugeordnet ist.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Chat",,
|
||||
"Check Duplicate","Duplikat prüfen",,
|
||||
"Code","Code",,
|
||||
"Configurations","Konfigurationen",,
|
||||
"Connection successful","Verbindung erfolgreich",,
|
||||
"Content","Inhalt",,
|
||||
"Context",,,
|
||||
"Create message","Nachricht erstellen",,
|
||||
"Default","Standard",,
|
||||
"Default account","Standardkonto",,
|
||||
"Delete","Löschen",,
|
||||
"Deleted","Gelöscht",,
|
||||
"Draft","Entwurf",,
|
||||
"Email","E-Mail",,
|
||||
"Email Accounts","E-Mail-Konten",,
|
||||
"Email address","E-Mail-Adresse",,
|
||||
"Email addresses","E-Mail-Adressen",,
|
||||
"Email sending is in progress","Der E-Mail-Versand ist im Gange.",,
|
||||
"Email sending is in progress for %d messages.","Der E-Mail-Versand wird für %d-Nachrichten durchgeführt.",,
|
||||
"Emails","E-Mails",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","E-Mails abrufen",,
|
||||
"Forecasted Sent Date","Voraussichtliches Versanddatum",,
|
||||
"From","Von",,
|
||||
"Generate message","Nachricht erzeugen",,
|
||||
"Group","Gruppe",,
|
||||
"Host","Gastgeber",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Falsches Login oder Passwort",,
|
||||
"Informations","Informationen",,
|
||||
"Json",,,
|
||||
"Language","Sprache",,
|
||||
"Login","Login",,
|
||||
"Mail","Mail",,
|
||||
"Mail account","Mail-Konto",,
|
||||
"Mail accounts","Mail-Konten",,
|
||||
"Media Type","Medientyp",,
|
||||
"Message","Nachricht",,
|
||||
"Message destinated to","Nachricht, die bestimmt ist für",,
|
||||
"Messages","Nachrichten",,
|
||||
"Messages not sent","Nachrichten nicht gesendet",,
|
||||
"Model","Modell",,
|
||||
"Model empty. Please configure a model.","Modell leer. Bitte konfigurieren Sie ein Modell.",,
|
||||
"NONE","KEINE",,
|
||||
"Name","Name",,
|
||||
"No Mail content entered.","Es wurden keine Mail-Inhalte eingegeben.",,
|
||||
"POP","POP",,
|
||||
"Password","Passwort",,
|
||||
"Please configure a template","Bitte konfigurieren Sie eine Vorlage",,
|
||||
"Please select one or more messages.","Bitte wählen Sie eine oder mehrere Nachrichten aus.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Port",,
|
||||
"Print","Drucken",,
|
||||
"Provided settings are wrong, please modify them and try again","Vorausgesetzt, die Einstellungen sind falsch, bitte ändern Sie sie und versuchen Sie es erneut.",,
|
||||
"Received","Erhalten",,
|
||||
"Recipient","Empfänger",,
|
||||
"Recipient address","Empfängeradresse",,
|
||||
"Recipients","Empfänger",,
|
||||
"Record Id","Aufzeichnungs-ID",,
|
||||
"Record Name","Datensatzname",,
|
||||
"Regenerate messages","Nachrichten neu generieren",,
|
||||
"Related to","In Bezug auf",,
|
||||
"Related to1 select","Bezogen auf 1 Auswahl",,
|
||||
"Related to2 select","Bezogen auf2 select",,
|
||||
"Reply to","Antwort auf",,
|
||||
"Resend messages","Nachrichten erneut senden",,
|
||||
"Routings","Arbeitspläne",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","STARTTASTEN",,
|
||||
"Select template","Vorlage auswählen",,
|
||||
"Send","Senden",,
|
||||
"Sender (User)","Absender (Benutzer)",,
|
||||
"Sender's email address is null or empty","Die E-Mail-Adresse des Absenders ist null oder leer.",,
|
||||
"Sent","Gesendet",,
|
||||
"Sent by email","Per E-Mail versendet",,
|
||||
"Sent date","Sendedatum",,
|
||||
"Server Type","Servertyp",,
|
||||
"Signature","Unterschrift",,
|
||||
"Status","Status",,
|
||||
"Subject","Betreff",,
|
||||
"System","System",,
|
||||
"TO/CC/BCC recipient's email address is empty","Die E-Mail-Adresse des TO/CC/BCC-Empfängers ist leer.",,
|
||||
"Target receptor","Zielrezeptor",,
|
||||
"Template","Vorlage",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Template-Regeln",,
|
||||
"Templates","Vorlagen",,
|
||||
"Test connection","Prüfverbindung",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Es gibt bereits ein Standardkonto.",,
|
||||
"To","An",,
|
||||
"Type","Typ",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS"," Der Server konnte nicht erreicht werden. Bitte überprüfen Sie Host,Port und SSL/TLS.",,
|
||||
"User","Benutzer",,
|
||||
"Valid","Gültig",,
|
||||
"Validate","Validieren",,
|
||||
"Waiting model: %s","Wartendes Modell: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Dein Zielrezeptor ist nicht gültig. Bitte überprüfen Sie es.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.",,,
|
||||
"Address",,,
|
||||
"Address Block",,,
|
||||
"All messages",,,
|
||||
"Bcc",,,
|
||||
"Cannot regenerate message without related model.",,,
|
||||
"Cannot regenerate message without template associated to message.",,,
|
||||
"Cc",,,
|
||||
"Chat",,,
|
||||
"Check Duplicate",,,
|
||||
"Code",,,
|
||||
"Configurations",,,
|
||||
"Connection successful",,,
|
||||
"Content",,,
|
||||
"Context",,,
|
||||
"Create message",,,
|
||||
"Default",,,
|
||||
"Default account",,,
|
||||
"Delete",,,
|
||||
"Deleted",,,
|
||||
"Draft",,,
|
||||
"Email",,,
|
||||
"Email Accounts",,,
|
||||
"Email address",,,
|
||||
"Email addresses",,,
|
||||
"Email sending is in progress",,,
|
||||
"Email sending is in progress for %d messages.",,,
|
||||
"Emails",,,
|
||||
"Expr. value",,,
|
||||
"Fetch emails",,,
|
||||
"Forecasted Sent Date",,,
|
||||
"From",,,
|
||||
"Generate message",,,
|
||||
"Group",,,
|
||||
"Host",,,
|
||||
"IMAP",,,
|
||||
"In progress",,,
|
||||
"Incorrect login or password",,,
|
||||
"Informations",,,
|
||||
"Json",,,
|
||||
"Language",,,
|
||||
"Login",,,
|
||||
"Mail",,,
|
||||
"Mail account",,,
|
||||
"Mail accounts",,,
|
||||
"Media Type",,,
|
||||
"Message",,,
|
||||
"Message destinated to",,,
|
||||
"Messages",,,
|
||||
"Messages not sent",,,
|
||||
"Model",,,
|
||||
"Model empty. Please configure a model.",,,
|
||||
"NONE",,,
|
||||
"Name",,,
|
||||
"No Mail content entered.",,,
|
||||
"POP",,,
|
||||
"Password",,,
|
||||
"Please configure a template",,,
|
||||
"Please select one or more messages.",,,
|
||||
"Please set the email template to send",,,
|
||||
"Port",,,
|
||||
"Print",,,
|
||||
"Provided settings are wrong, please modify them and try again",,,
|
||||
"Received",,,
|
||||
"Recipient",,,
|
||||
"Recipient address",,,
|
||||
"Recipients",,,
|
||||
"Record Id",,,
|
||||
"Record Name",,,
|
||||
"Regenerate messages",,,
|
||||
"Related to",,,
|
||||
"Related to1 select",,,
|
||||
"Related to2 select",,,
|
||||
"Reply to",,,
|
||||
"Resend messages",,,
|
||||
"Routings",,,
|
||||
"SMTP",,,
|
||||
"SSL",,,
|
||||
"SSL/STARTTLS",,,
|
||||
"STARTTLS",,,
|
||||
"Select template",,,
|
||||
"Send",,,
|
||||
"Sender (User)",,,
|
||||
"Sender's email address is null or empty",,,
|
||||
"Sent",,,
|
||||
"Sent by email",,,
|
||||
"Sent date",,,
|
||||
"Server Type",,,
|
||||
"Signature",,,
|
||||
"Status",,,
|
||||
"Subject","Subject",,
|
||||
"System",,,
|
||||
"TO/CC/BCC recipient's email address is empty",,,
|
||||
"Target receptor",,,
|
||||
"Template",,,
|
||||
"Template Context",,,
|
||||
"Template Rules",,,
|
||||
"Templates",,,
|
||||
"Test connection",,,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account",,,
|
||||
"To",,,
|
||||
"Type",,,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS",,,
|
||||
"User",,,
|
||||
"Valid",,,
|
||||
"Validate",,,
|
||||
"Waiting model: %s",,,
|
||||
"Your target receptor is not valid. Please check it.",,,
|
||||
"user@mydomain.com",,,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","Los mensajes %d se han regenerado con éxito y se añaden errores %d.",,
|
||||
"Address","Dirección",,
|
||||
"Address Block","Bloque de direcciones",,
|
||||
"All messages","Todos los mensajes",,
|
||||
"Bcc","CCO",,
|
||||
"Cannot regenerate message without related model.","No se puede regenerar el mensaje sin el modelo relacionado.",,
|
||||
"Cannot regenerate message without template associated to message.","No se puede regenerar el mensaje sin la plantilla asociada al mensaje.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Chat",,
|
||||
"Check Duplicate","Comprobar Duplicado",,
|
||||
"Code","Código",,
|
||||
"Configurations","Configuraciones",,
|
||||
"Connection successful","Conexión exitosa",,
|
||||
"Content","Contenido",,
|
||||
"Context",,,
|
||||
"Create message","Crear mensaje",,
|
||||
"Default","Predeterminado",,
|
||||
"Default account","Cuenta por defecto",,
|
||||
"Delete","Borrar",,
|
||||
"Deleted","Borrado",,
|
||||
"Draft","Proyecto de",,
|
||||
"Email","Correo electrónico",,
|
||||
"Email Accounts","Cuentas de correo",,
|
||||
"Email address","Dirección de correo electrónico",,
|
||||
"Email addresses","Direcciones de correo electrónico",,
|
||||
"Email sending is in progress","El envío de correo electrónico está en curso",,
|
||||
"Email sending is in progress for %d messages.","El envío de correo electrónico está en progreso para los mensajes %d.",,
|
||||
"Emails","Emails",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","Obtener correos electrónicos",,
|
||||
"Forecasted Sent Date","Fecha de envío prevista",,
|
||||
"From","Desde",,
|
||||
"Generate message","Generar mensaje",,
|
||||
"Group","Grupo",,
|
||||
"Host","Anfitrión",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Nombre de usuario o contraseña incorrectos",,
|
||||
"Informations","Informaciones",,
|
||||
"Json",,,
|
||||
"Language","Idioma",,
|
||||
"Login","Iniciar sesión",,
|
||||
"Mail","Correo",,
|
||||
"Mail account","Cuenta de correo",,
|
||||
"Mail accounts","Cuentas de correo",,
|
||||
"Media Type","Tipo de medio",,
|
||||
"Message","Mensaje",,
|
||||
"Message destinated to","Mensaje destinado a",,
|
||||
"Messages","Mensajes",,
|
||||
"Messages not sent","Mensajes no enviados",,
|
||||
"Model","Modelo",,
|
||||
"Model empty. Please configure a model.","Modelo vacío. Por favor, configure un modelo.",,
|
||||
"NONE","NINGUNA",,
|
||||
"Name","Nombre",,
|
||||
"No Mail content entered.","No se ha introducido ningún contenido de Mail.",,
|
||||
"POP","COP",,
|
||||
"Password","Contraseña",,
|
||||
"Please configure a template","Por favor, configure una plantilla",,
|
||||
"Please select one or more messages.","Por favor, seleccione uno o más mensajes.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Puerto",,
|
||||
"Print","Imprimir",,
|
||||
"Provided settings are wrong, please modify them and try again","Si la configuración es incorrecta, por favor, modifíquela e inténtelo de nuevo",,
|
||||
"Received","Recibido",,
|
||||
"Recipient","Destinatario",,
|
||||
"Recipient address","Dirección del destinatario",,
|
||||
"Recipients","Destinatarios",,
|
||||
"Record Id","Id. de registro",,
|
||||
"Record Name","Nombre del registro",,
|
||||
"Regenerate messages","Regenerar mensajes",,
|
||||
"Related to","Relacionado con",,
|
||||
"Related to1 select","Relacionado con1 seleccionar",,
|
||||
"Related to2 select","Relacionado con2 seleccionar",,
|
||||
"Reply to","Responder a",,
|
||||
"Resend messages","Reenviar mensajes",,
|
||||
"Routings","Hojas de ruta",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","INICIO",,
|
||||
"Select template","Seleccionar plantilla",,
|
||||
"Send","Enviar",,
|
||||
"Sender (User)","Remitente (Usuario)",,
|
||||
"Sender's email address is null or empty","La dirección de correo electrónico del remitente es nula o vacía",,
|
||||
"Sent","Enviado",,
|
||||
"Sent by email","Enviado por correo electrónico",,
|
||||
"Sent date","Fecha de envío",,
|
||||
"Server Type","Tipo de servidor",,
|
||||
"Signature","Firma",,
|
||||
"Status","Estado",,
|
||||
"Subject","Tema",,
|
||||
"System","Sistema",,
|
||||
"TO/CC/BCC recipient's email address is empty","La dirección de correo electrónico del destinatario de TO/CC/BCC está vacía",,
|
||||
"Target receptor","Receptor de destino",,
|
||||
"Template","Plantilla",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Reglas del modelo",,
|
||||
"Templates","Plantillas",,
|
||||
"Test connection","Conexión de prueba",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Ya hay una cuenta por defecto",,
|
||||
"To","Para",,
|
||||
"Type","Tipo",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Incapaz de llegar al servidor. Por favor, compruebe Host, Puerto y SSL/TLS",,
|
||||
"User","Usuario",,
|
||||
"Valid","Válido",,
|
||||
"Validate","Validar",,
|
||||
"Waiting model: %s","Modelo en espera: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Su receptor objetivo no es válido. Por favor, compruébalo.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","%d messages regénérés avec succès et %d erreurs.",,
|
||||
"Address","Adresse email",,
|
||||
"Address Block","Bloc d'adresse",,
|
||||
"All messages","Tous les messages",,
|
||||
"Bcc","Cci",,
|
||||
"Cannot regenerate message without related model.","Vous ne pouvez pas regénérer un message qui n'a pas d'objet en relation.",,
|
||||
"Cannot regenerate message without template associated to message.","Vous ne pouvez pas regénérer un message sans modèle associé.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Messagerie interne",,
|
||||
"Check Duplicate","Vérifier doublons",,
|
||||
"Code","Code",,
|
||||
"Configurations","Configurations",,
|
||||
"Connection successful","Connexion réussie",,
|
||||
"Content","Contenu",,
|
||||
"Context",,,
|
||||
"Create message","Créer message",,
|
||||
"Default","Par défaut",,
|
||||
"Default account","Compte par défaut",,
|
||||
"Delete","Supprimer",,
|
||||
"Deleted","Supprimée",,
|
||||
"Draft","Brouillon",,
|
||||
"Email","Email",,
|
||||
"Email Accounts","Comptes SMTP",,
|
||||
"Email address","Adresse Email",,
|
||||
"Email addresses","Adresses email",,
|
||||
"Email sending is in progress","Envoi d'email en cours",,
|
||||
"Email sending is in progress for %d messages.",,,
|
||||
"Emails","Emails",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails",,,
|
||||
"Forecasted Sent Date","Date prévue d'envoi",,
|
||||
"From","De",,
|
||||
"Generate message","Générer message",,
|
||||
"Group",,,
|
||||
"Host","Hôte",,
|
||||
"IMAP",,,
|
||||
"In progress","En cours",,
|
||||
"Incorrect login or password","Identifiant ou mot de passe incorrect",,
|
||||
"Informations","Informations",,
|
||||
"Json",,,
|
||||
"Language",,,
|
||||
"Login","Identifiant",,
|
||||
"Mail","Courrier",,
|
||||
"Mail account","Compte email",,
|
||||
"Mail accounts","Comptes email",,
|
||||
"Media Type","Type de média",,
|
||||
"Message","Message",,
|
||||
"Message destinated to","Message destiné à",,
|
||||
"Messages",,,
|
||||
"Messages not sent","Messages non envoyés",,
|
||||
"Model","Objet métier",,
|
||||
"Model empty. Please configure a model.","Model vide. Merci de configurer un modèle",,
|
||||
"NONE","Non",,
|
||||
"Name","Intitulé",,
|
||||
"No Mail content entered.","Courrier sans contenu.",,
|
||||
"POP",,,
|
||||
"Password","Mot de passe",,
|
||||
"Please configure a template","Veuillez configurer un modèle",,
|
||||
"Please select one or more messages.","Veuillez séléctionner un ou plusieurs messages.",,
|
||||
"Please set the email template to send","Veuillez configurer le modèle d'email à envoyer.",,
|
||||
"Port","Port",,
|
||||
"Print","Imprimer",,
|
||||
"Provided settings are wrong, please modify them and try again",,,
|
||||
"Received","Reçu",,
|
||||
"Recipient","Destinataire",,
|
||||
"Recipient address","Adresse destinataire",,
|
||||
"Recipients","Destinataires",,
|
||||
"Record Id",,,
|
||||
"Record Name",,,
|
||||
"Regenerate messages","Regénérer les messages",,
|
||||
"Related to","Associé à ",,
|
||||
"Related to1 select","Lié à (1) sélection",,
|
||||
"Related to2 select","Lié à (2) sélection",,
|
||||
"Reply to","Répondre à",,
|
||||
"Resend messages","Renvoyer les messages",,
|
||||
"Routings","Routage",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS",,,
|
||||
"STARTTLS",,,
|
||||
"Select template","Sélectionner un modèle",,
|
||||
"Send","Envoyer",,
|
||||
"Sender (User)","Expéditeur (Utilisateur)",,
|
||||
"Sender's email address is null or empty",,,
|
||||
"Sent","Envoyé",,
|
||||
"Sent by email","Envoyé par email",,
|
||||
"Sent date","Date d'envoi",,
|
||||
"Server Type","Type serveur",,
|
||||
"Signature","Signature",,
|
||||
"Status","Statut",,
|
||||
"Subject","Sujet/Objet",,
|
||||
"System","Système",,
|
||||
"TO/CC/BCC recipient's email address is empty","Les adresses email TO/CC/BCC sont vides.",,
|
||||
"Target receptor","Destinataire cible",,
|
||||
"Template","Modèle",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Règles des modèles",,
|
||||
"Templates","Modèles",,
|
||||
"Test connection","Tester connexion",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)","Le modèle du modèle d'email (%s) est différent du modèle générant l'email (%s)",,
|
||||
"There is already a default account","Il existe déjà une compte email par défaut.",,
|
||||
"To","À",,
|
||||
"Type","Type",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Impossible de contacter le serveur. Merci de vérifier l'hôte, le port et le SSL/TLS",,
|
||||
"User",,,
|
||||
"Valid","Valide",,
|
||||
"Validate","Valider",,
|
||||
"Waiting model: %s",,,
|
||||
"Your target receptor is not valid. Please check it.",,,
|
||||
"user@mydomain.com",,,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","%d messages è stato rigenerato con successo e %d errors append.",,
|
||||
"Address","Indirizzo",,
|
||||
"Address Block","Blocco indirizzo",,
|
||||
"All messages","Tutti i messaggi",,
|
||||
"Bcc","Bcc",,
|
||||
"Cannot regenerate message without related model.","Non è possibile rigenerare il messaggio senza il relativo modello.",,
|
||||
"Cannot regenerate message without template associated to message.","Non può rigenerare un messaggio senza un modello associato al messaggio.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Chiacchierata",,
|
||||
"Check Duplicate","Controlla Duplicazione",,
|
||||
"Code","Codice",,
|
||||
"Configurations","Configurazioni",,
|
||||
"Connection successful","Connessione riuscita",,
|
||||
"Content","Contenuto",,
|
||||
"Context",,,
|
||||
"Create message","Crea messaggio",,
|
||||
"Default","Predefinito",,
|
||||
"Default account","Conto predefinito",,
|
||||
"Delete","Cancellare",,
|
||||
"Deleted","Soppresso",,
|
||||
"Draft","Bozza",,
|
||||
"Email","Email eMail",,
|
||||
"Email Accounts","Account di posta elettronica",,
|
||||
"Email address","Indirizzo e-mail",,
|
||||
"Email addresses","Indirizzi e-mail",,
|
||||
"Email sending is in progress","L'invio di e-mail è in corso",,
|
||||
"Email sending is in progress for %d messages.","L'invio di e-mail è in corso per i messaggi %d.",,
|
||||
"Emails","Email",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","Recuperare le e-mail",,
|
||||
"Forecasted Sent Date","Data di invio prevista",,
|
||||
"From","Da",,
|
||||
"Generate message","Genera messaggio",,
|
||||
"Group","Gruppo",,
|
||||
"Host","Ospite",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Login o password non corretti",,
|
||||
"Informations","Informazioni",,
|
||||
"Json",,,
|
||||
"Language","Lingua",,
|
||||
"Login","Accedi",,
|
||||
"Mail","Posta",,
|
||||
"Mail account","Conto postale",,
|
||||
"Mail accounts","Conti postali",,
|
||||
"Media Type","Tipo di supporto",,
|
||||
"Message","Messaggio",,
|
||||
"Message destinated to","Messaggio destinato a",,
|
||||
"Messages","Messaggi",,
|
||||
"Messages not sent","Messaggi non inviati",,
|
||||
"Model","Modello",,
|
||||
"Model empty. Please configure a model.","Modello vuoto. Si prega di configurare un modello.",,
|
||||
"NONE","NESSUNO",,
|
||||
"Name","Nome",,
|
||||
"No Mail content entered.","Nessun contenuto della posta inserito.",,
|
||||
"POP","POP",,
|
||||
"Password","La password",,
|
||||
"Please configure a template","Configurare un modello",,
|
||||
"Please select one or more messages.","Selezionare uno o più messaggi.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Porto",,
|
||||
"Print","Stampa",,
|
||||
"Provided settings are wrong, please modify them and try again","Se le impostazioni sono sbagliate, si prega di modificarle e riprovare.",,
|
||||
"Received","Ricevuto",,
|
||||
"Recipient","Destinatario",,
|
||||
"Recipient address","Indirizzo del destinatario",,
|
||||
"Recipients","Destinatari",,
|
||||
"Record Id","Id record",,
|
||||
"Record Name","Nome del record",,
|
||||
"Regenerate messages","Rigenerazione dei messaggi",,
|
||||
"Related to","Relativo a",,
|
||||
"Related to1 select","Relativo a1 select",,
|
||||
"Related to2 select","Relativo a2 select",,
|
||||
"Reply to","Rispondi a",,
|
||||
"Resend messages","Inviare nuovamente i messaggi",,
|
||||
"Routings","Percorsi",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","STELLE",,
|
||||
"Select template","Seleziona modello",,
|
||||
"Send","Inviare",,
|
||||
"Sender (User)","Mittente (Utente)",,
|
||||
"Sender's email address is null or empty","L'indirizzo email del mittente è nullo o vuoto",,
|
||||
"Sent","Inviato",,
|
||||
"Sent by email","Inviato via e-mail",,
|
||||
"Sent date","Data di invio",,
|
||||
"Server Type","Tipo di server",,
|
||||
"Signature","Firma",,
|
||||
"Status","Stato",,
|
||||
"Subject","Oggetto",,
|
||||
"System","Sistema",,
|
||||
"TO/CC/BCC recipient's email address is empty","L'indirizzo e-mail del destinatario TO/CC/BCC è vuoto",,
|
||||
"Target receptor","Destinatario recettore",,
|
||||
"Template","Modello",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Regole del modello",,
|
||||
"Templates","Modelli",,
|
||||
"Test connection","Connessione di prova",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","C'è già un account predefinito",,
|
||||
"To","A",,
|
||||
"Type","Tipo",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Impossibile raggiungere il server. Per favore, controlla Host, Port e SSL/TLS.",,
|
||||
"User","Utente",,
|
||||
"Valid","Valido",,
|
||||
"Validate","Convalida",,
|
||||
"Waiting model: %s","Modello di attesa: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Il ricevitore target non è valido. Per favore, controlla.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","%d berichten is met succes geregenereerd en %d fouten zijn toegevoegd.",,
|
||||
"Address","Adres",,
|
||||
"Address Block","Adresblok",,
|
||||
"All messages","Alle berichten",,
|
||||
"Bcc","Bcc",,
|
||||
"Cannot regenerate message without related model.","Kan geen bericht regenereren zonder gerelateerd model.",,
|
||||
"Cannot regenerate message without template associated to message.","Kan geen bericht regenereren zonder sjabloon gekoppeld aan het bericht.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Chat",,
|
||||
"Check Duplicate","Controleer Duplicaat",,
|
||||
"Code","Code",,
|
||||
"Configurations","Configuraties",,
|
||||
"Connection successful","Aansluiting geslaagd",,
|
||||
"Content","Inhoud",,
|
||||
"Context",,,
|
||||
"Create message","Bericht aanmaken",,
|
||||
"Default","Standaard",,
|
||||
"Default account","Standaard rekening",,
|
||||
"Delete","Schrappen",,
|
||||
"Deleted","Verwijderd",,
|
||||
"Draft","Ontwerp",,
|
||||
"Email","E-mail",,
|
||||
"Email Accounts","E-mailaccounts",,
|
||||
"Email address","E-mail adres",,
|
||||
"Email addresses","E-mail adressen",,
|
||||
"Email sending is in progress","E-mailverzending is in volle gang",,
|
||||
"Email sending is in progress for %d messages.","Voor %d-berichten is het versturen van e-mails aan de gang.",,
|
||||
"Emails","E-mails",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","E-mails ophalen",,
|
||||
"Forecasted Sent Date","Verwachte verzenddatum",,
|
||||
"From","Van",,
|
||||
"Generate message","Bericht genereren",,
|
||||
"Group","Groep",,
|
||||
"Host","Gastheer",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Onjuiste login of wachtwoord",,
|
||||
"Informations","Informatie",,
|
||||
"Json",,,
|
||||
"Language","Taal",,
|
||||
"Login","Inloggen",,
|
||||
"Mail","Mail",,
|
||||
"Mail account","Mail account",,
|
||||
"Mail accounts","Mail accounts",,
|
||||
"Media Type","Type media",,
|
||||
"Message","Bericht",,
|
||||
"Message destinated to","Bericht bestemd voor",,
|
||||
"Messages","Berichten",,
|
||||
"Messages not sent","Berichten niet verzonden",,
|
||||
"Model","Model",,
|
||||
"Model empty. Please configure a model.","Model leeg. Configureer een model.",,
|
||||
"NONE","GEEN",,
|
||||
"Name","Naam",,
|
||||
"No Mail content entered.","Geen inhoud van de e-mail ingevoerd.",,
|
||||
"POP","POP",,
|
||||
"Password","Wachtwoord",,
|
||||
"Please configure a template","Configureer een sjabloon",,
|
||||
"Please select one or more messages.","Selecteer een of meer berichten.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Haven",,
|
||||
"Print","Afdrukken",,
|
||||
"Provided settings are wrong, please modify them and try again","Als de instellingen verkeerd zijn, wijzig ze dan en probeer het opnieuw.",,
|
||||
"Received","Ontvangen",,
|
||||
"Recipient","Ontvanger",,
|
||||
"Recipient address","Adres van de ontvanger",,
|
||||
"Recipients","Ontvangers",,
|
||||
"Record Id","Verslag Id",,
|
||||
"Record Name","Verslagnaam",,
|
||||
"Regenerate messages","Berichten regenereren",,
|
||||
"Related to","Met betrekking tot",,
|
||||
"Related to1 select","Gerelateerd aan1 selecteer",,
|
||||
"Related to2 select","Gerelateerd aan2 selecteer",,
|
||||
"Reply to","Antwoord op",,
|
||||
"Resend messages","Berichten opnieuw verzenden",,
|
||||
"Routings","Routes",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","STARTTLIJNEN",,
|
||||
"Select template","Sjabloon kiezen",,
|
||||
"Send","Verzenden",,
|
||||
"Sender (User)","Afzender (gebruiker)",,
|
||||
"Sender's email address is null or empty","E-mail adres van de afzender is ongeldig of leeg",,
|
||||
"Sent","Verzonden",,
|
||||
"Sent by email","Verzonden per e-mail",,
|
||||
"Sent date","Verzonden datum",,
|
||||
"Server Type","Servertype",,
|
||||
"Signature","Handtekening",,
|
||||
"Status","Status",,
|
||||
"Subject","Onderwerp",,
|
||||
"System","Systeem",,
|
||||
"TO/CC/BCC recipient's email address is empty","Het e-mailadres van de TO/CC/BCC-ontvanger is leeg",,
|
||||
"Target receptor","Doelreceptor",,
|
||||
"Template","Sjabloon",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Sjabloonregels",,
|
||||
"Templates","Sjablonen",,
|
||||
"Test connection","Testaansluiting",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Er is al een standaard account",,
|
||||
"To","Naar",,
|
||||
"Type","Type",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Kan de server niet bereiken. Gelieve te controleren Gastheer, Haven en SSL/TLS",,
|
||||
"User","Gebruiker",,
|
||||
"Valid","Geldig",,
|
||||
"Validate","Valideren",,
|
||||
"Waiting model: %s","Wachten model: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Uw doelreceptor is niet geldig. Controleer het alstublieft.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","komunikaty %d zostały pomyślnie zregenerowane, a %d błędów dołączone.",,
|
||||
"Address","Adres",,
|
||||
"Address Block","Blok adresowy",,
|
||||
"All messages","Wszystkie wiadomości",,
|
||||
"Bcc","Bcc",,
|
||||
"Cannot regenerate message without related model.","Nie można zregenerować wiadomości bez powiązanego modelu.",,
|
||||
"Cannot regenerate message without template associated to message.","Nie można regenerować wiadomości bez szablonu związanego z wiadomością.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Czat",,
|
||||
"Check Duplicate","Sprawdź duplikat",,
|
||||
"Code","Kod",,
|
||||
"Configurations","Konfiguracje",,
|
||||
"Connection successful","Pomyślne połączenie",,
|
||||
"Content","Zawartość",,
|
||||
"Context",,,
|
||||
"Create message","Tworzenie wiadomości",,
|
||||
"Default","Domyślnie",,
|
||||
"Default account","Konto domyślne",,
|
||||
"Delete","Skreślenie",,
|
||||
"Deleted","Skreślony",,
|
||||
"Draft","Wstępny projekt",,
|
||||
"Email","Poczta elektroniczna",,
|
||||
"Email Accounts","Konta e-mail",,
|
||||
"Email address","Adres e-mail",,
|
||||
"Email addresses","Adresy poczty elektronicznej",,
|
||||
"Email sending is in progress","Trwa wysyłanie poczty elektronicznej",,
|
||||
"Email sending is in progress for %d messages.","Wysyłanie wiadomości e-mail jest w toku dla wiadomości %d.",,
|
||||
"Emails","Poczta elektroniczna",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","Pociągnij e-maile",,
|
||||
"Forecasted Sent Date","Przewidywana data wysłania",,
|
||||
"From","Od",,
|
||||
"Generate message","Generowanie komunikatu",,
|
||||
"Group","Grupa",,
|
||||
"Host","Gospodarz",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Niepoprawny login lub hasło",,
|
||||
"Informations","Informacje",,
|
||||
"Json",,,
|
||||
"Language","Język",,
|
||||
"Login","Login",,
|
||||
"Mail","poczta",,
|
||||
"Mail account","Konto pocztowe",,
|
||||
"Mail accounts","Konta pocztowe",,
|
||||
"Media Type","Typ nośnika",,
|
||||
"Message","Wiadomość",,
|
||||
"Message destinated to","Wiadomość przeznaczona dla",,
|
||||
"Messages","Komunikaty",,
|
||||
"Messages not sent","Komunikaty nie są wysyłane",,
|
||||
"Model","Model",,
|
||||
"Model empty. Please configure a model.","Model pusty. Proszę skonfigurować model.",,
|
||||
"NONE","BRAK.",,
|
||||
"Name","Nazwa",,
|
||||
"No Mail content entered.","Nie wprowadzono zawartości Mail.",,
|
||||
"POP","POP",,
|
||||
"Password","Hasło",,
|
||||
"Please configure a template","Proszę skonfigurować szablon",,
|
||||
"Please select one or more messages.","Proszę wybrać jedną lub więcej wiadomości.",,
|
||||
"Please set the email template to send","Veuillez configurer le modèle d'email à envoyer.",,
|
||||
"Port","Port",,
|
||||
"Print","Drukuj",,
|
||||
"Provided settings are wrong, please modify them and try again","Jeżeli ustawienia są błędne, należy je zmodyfikować i spróbować ponownie.",,
|
||||
"Received","Otrzymany",,
|
||||
"Recipient","Odbiorca",,
|
||||
"Recipient address","Adres odbiorcy",,
|
||||
"Recipients","Odbiorcy",,
|
||||
"Record Id","Numer rekordu",,
|
||||
"Record Name","Nazwa rekordu",,
|
||||
"Regenerate messages","Regeneruj wiadomości",,
|
||||
"Related to","Związane z",,
|
||||
"Related to1 select","W odniesieniu do1 wybierz",,
|
||||
"Related to2 select","W odniesieniu do2 wybierz",,
|
||||
"Reply to","Odpowiedź do",,
|
||||
"Resend messages","Ponowne wysyłanie wiadomości",,
|
||||
"Routings","Trasy",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","STARTKI",,
|
||||
"Select template","Wybór szablonu",,
|
||||
"Send","Wyślij",,
|
||||
"Sender (User)","Nadawca (użytkownik)",,
|
||||
"Sender's email address is null or empty","Adres e-mail nadawcy jest pusty lub nieważny",,
|
||||
"Sent","Wysłane",,
|
||||
"Sent by email","Wysłane pocztą elektroniczną",,
|
||||
"Sent date","Data wysłania",,
|
||||
"Server Type","Typ serwera",,
|
||||
"Signature","Podpisanie",,
|
||||
"Status","Status",,
|
||||
"Subject","Przedmiot",,
|
||||
"System","System",,
|
||||
"TO/CC/BCC recipient's email address is empty","Adres e-mail odbiorcy TO/CC/BCC jest pusty",,
|
||||
"Target receptor","Receptor docelowy",,
|
||||
"Template","Szablon",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Wzór regulaminu",,
|
||||
"Templates","Szablony",,
|
||||
"Test connection","Przyłącze testowe",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Istnieje już konto domyślne",,
|
||||
"To","Do",,
|
||||
"Type","Typ",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Nie można dotrzeć do serwera. Proszę sprawdzić hosta, port i SSL/TLS.",,
|
||||
"User","Użytkownik",,
|
||||
"Valid","Obowiązuje",,
|
||||
"Validate","Zatwierdzić",,
|
||||
"Waiting model: %s","Model oczekiwania: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Twój docelowy receptor jest nieważny. Proszę to sprawdzić.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","Mensagens %d foram regeneradas com sucesso e erros %d anexados.",,
|
||||
"Address","Morada",,
|
||||
"Address Block","Bloco de endereços",,
|
||||
"All messages","Todas as mensagens",,
|
||||
"Bcc","Bcc",,
|
||||
"Cannot regenerate message without related model.","Não é possível regenerar a mensagem sem o modelo relacionado.",,
|
||||
"Cannot regenerate message without template associated to message.","Não é possível gerar novamente a mensagem sem o modelo associado à mensagem.",,
|
||||
"Cc","Cc",,
|
||||
"Chat","Bate-papo",,
|
||||
"Check Duplicate","Verificar duplicata",,
|
||||
"Code","Código",,
|
||||
"Configurations","Configurações",,
|
||||
"Connection successful","Conexão bem-sucedida",,
|
||||
"Content","Conteúdo",,
|
||||
"Context",,,
|
||||
"Create message","Criar mensagem",,
|
||||
"Default","Padrão",,
|
||||
"Default account","Conta padrão",,
|
||||
"Delete","Eliminar",,
|
||||
"Deleted","Eliminado",,
|
||||
"Draft","Rascunho",,
|
||||
"Email","Email",,
|
||||
"Email Accounts","Contas de e-mail",,
|
||||
"Email address","Endereço de e-mail",,
|
||||
"Email addresses","Endereços de e-mail",,
|
||||
"Email sending is in progress","O envio de e-mail está em andamento",,
|
||||
"Email sending is in progress for %d messages.","O envio de e-mail está em andamento para mensagens %d.",,
|
||||
"Emails","Emails",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","Obter e-mails",,
|
||||
"Forecasted Sent Date","Data de Envio Prevista",,
|
||||
"From","De",,
|
||||
"Generate message","Gerar mensagem",,
|
||||
"Group","Grupo (Grupo)",,
|
||||
"Host","Anfitrião",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Login ou senha incorretos",,
|
||||
"Informations","Informações",,
|
||||
"Json",,,
|
||||
"Language","Idioma",,
|
||||
"Login","Login",,
|
||||
"Mail","Correspondência",,
|
||||
"Mail account","Conta de correio",,
|
||||
"Mail accounts","Contas de correio",,
|
||||
"Media Type","Tipo de mídia",,
|
||||
"Message","Mensagem",,
|
||||
"Message destinated to","Mensagem destinada a",,
|
||||
"Messages","Mensagens",,
|
||||
"Messages not sent","Mensagens não enviadas",,
|
||||
"Model","Modelo",,
|
||||
"Model empty. Please configure a model.","Modelo vazio. Por favor, configure um modelo.",,
|
||||
"NONE","NENHUNS",,
|
||||
"Name","Nome e Sobrenome",,
|
||||
"No Mail content entered.","Nenhum conteúdo de e-mail inserido.",,
|
||||
"POP","POP",,
|
||||
"Password","Senha",,
|
||||
"Please configure a template","Por favor, configure um modelo",,
|
||||
"Please select one or more messages.","Selecione uma ou mais mensagens.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Porto",,
|
||||
"Print","Imprimir",,
|
||||
"Provided settings are wrong, please modify them and try again","Desde que as configurações estejam erradas, por favor, modifique-as e tente novamente",,
|
||||
"Received","Recebido",,
|
||||
"Recipient","Destinatário",,
|
||||
"Recipient address","Endereço do destinatário",,
|
||||
"Recipients","Destinatários",,
|
||||
"Record Id","Registrar Id",,
|
||||
"Record Name","Nome do registro",,
|
||||
"Regenerate messages","Regenerar mensagens",,
|
||||
"Related to","Relacionado a",,
|
||||
"Related to1 select","Relacionado a1 select",,
|
||||
"Related to2 select","Relacionado a2 select",,
|
||||
"Reply to","Responder a",,
|
||||
"Resend messages","Reenviar mensagens",,
|
||||
"Routings","Roteiros",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","INÍCIO",,
|
||||
"Select template","Selecionar modelo",,
|
||||
"Send","Enviar",,
|
||||
"Sender (User)","Remetente (Usuário)",,
|
||||
"Sender's email address is null or empty","O endereço de e-mail do remetente é nulo ou vazio",,
|
||||
"Sent","Enviado",,
|
||||
"Sent by email","Enviado por e-mail",,
|
||||
"Sent date","Data de envio",,
|
||||
"Server Type","Tipo de servidor",,
|
||||
"Signature","Assinatura",,
|
||||
"Status","Estado",,
|
||||
"Subject","Assunto",,
|
||||
"System","Sistema",,
|
||||
"TO/CC/BCC recipient's email address is empty","O endereço de e-mail do destinatário do TO/CC/BCC está vazio",,
|
||||
"Target receptor","Receptor de destino",,
|
||||
"Template","Modelo",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Regras do modelo",,
|
||||
"Templates","Modelos",,
|
||||
"Test connection","Teste de conexão",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Já existe uma conta padrão",,
|
||||
"To","Para",,
|
||||
"Type","Tipo de",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Incapaz de chegar ao servidor. Por favor, verifique Host,Port e SSL/TLS",,
|
||||
"User","Usuário",,
|
||||
"Valid","Válido",,
|
||||
"Validate","Validar",,
|
||||
"Waiting model: %s","Modelo em espera: %s",,
|
||||
"Your target receptor is not valid. Please check it.","O seu receptor de alvo não é válido. Por favor, verifique.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,111 @@
|
||||
"key","message","comment","context"
|
||||
"%d messages has been regenerated successfully and %d errors append.","Сообщения %d были успешно восстановлены и добавлены ошибки %d.",,
|
||||
"Address","Адрес",,
|
||||
"Address Block","Адресный блок",,
|
||||
"All messages","Все сообщения",,
|
||||
"Bcc","Копы",,
|
||||
"Cannot regenerate message without related model.","Сообщение не может быть восстановлено без соответствующей модели.",,
|
||||
"Cannot regenerate message without template associated to message.","Невозможно регенерировать сообщение без шаблона, связанного с сообщением.",,
|
||||
"Cc","кубик",,
|
||||
"Chat","Чат",,
|
||||
"Check Duplicate","Проверка Дублирование",,
|
||||
"Code","Код",,
|
||||
"Configurations","Конфигурации",,
|
||||
"Connection successful","Подключение успешно",,
|
||||
"Content","Содержание",,
|
||||
"Context",,,
|
||||
"Create message","Создать сообщение",,
|
||||
"Default","По умолчанию",,
|
||||
"Default account","Счет по умолчанию",,
|
||||
"Delete","Удалить",,
|
||||
"Deleted","Удаленный",,
|
||||
"Draft","Проект",,
|
||||
"Email","Электронная почта",,
|
||||
"Email Accounts","Учетные записи электронной почты",,
|
||||
"Email address","Адрес электронной почты",,
|
||||
"Email addresses","Адреса электронной почты",,
|
||||
"Email sending is in progress","Отправка электронной почты продолжается",,
|
||||
"Email sending is in progress for %d messages.","Выполняется отправка электронной почты для %d сообщений.",,
|
||||
"Emails","Электронная почта",,
|
||||
"Expr. value",,,
|
||||
"Fetch emails","Получить сообщения электронной почты",,
|
||||
"Forecasted Sent Date","Прогнозируемая дата отправки",,
|
||||
"From","От",,
|
||||
"Generate message","Генерировать сообщение",,
|
||||
"Group","Группа",,
|
||||
"Host","Хозяин",,
|
||||
"IMAP","IMAP",,
|
||||
"In progress",,,
|
||||
"Incorrect login or password","Неправильный логин или пароль",,
|
||||
"Informations","Информация",,
|
||||
"Json",,,
|
||||
"Language","Язык",,
|
||||
"Login","Вход",,
|
||||
"Mail","Почта",,
|
||||
"Mail account","Почтовый ящик",,
|
||||
"Mail accounts","Почтовые ящики",,
|
||||
"Media Type","Тип носителя",,
|
||||
"Message","Сообщение",,
|
||||
"Message destinated to","Сообщение предназначено для",,
|
||||
"Messages","Сообщения",,
|
||||
"Messages not sent","Сообщения не отправлены",,
|
||||
"Model","Модель",,
|
||||
"Model empty. Please configure a model.","Модель пуста. Пожалуйста, сконфигурируйте модель.",,
|
||||
"NONE","НЕТ",,
|
||||
"Name","Имя",,
|
||||
"No Mail content entered.","Содержание почты не введено.",,
|
||||
"POP","СОЗ",,
|
||||
"Password","Пароль",,
|
||||
"Please configure a template","Пожалуйста, настройте шаблон",,
|
||||
"Please select one or more messages.","Пожалуйста, выберите одно или несколько сообщений.",,
|
||||
"Please set the email template to send",,,
|
||||
"Port","Порт",,
|
||||
"Print","Печать",,
|
||||
"Provided settings are wrong, please modify them and try again","Если настройки неверны, пожалуйста, измените их и повторите попытку.",,
|
||||
"Received","Получено",,
|
||||
"Recipient","Получатель",,
|
||||
"Recipient address","Адрес получателя",,
|
||||
"Recipients","Получатели",,
|
||||
"Record Id","Ид записи",,
|
||||
"Record Name","Имя записи",,
|
||||
"Regenerate messages","Восстановить сообщения",,
|
||||
"Related to","Связанный с",,
|
||||
"Related to1 select","Связанные с1 выбором",,
|
||||
"Related to2 select","Связанные с2 выбором",,
|
||||
"Reply to","Ответ на",,
|
||||
"Resend messages","Повторная отправка сообщений",,
|
||||
"Routings","Маршруты",,
|
||||
"SMTP","SMTP",,
|
||||
"SSL","SSL",,
|
||||
"SSL/STARTTLS","SSL/STARTTLS",,
|
||||
"STARTTLS","СТАРТТТЛС",,
|
||||
"Select template","Выберите шаблон",,
|
||||
"Send","Отправить",,
|
||||
"Sender (User)","Отправитель (Пользователь)",,
|
||||
"Sender's email address is null or empty","Адрес электронной почты отправителя нулевой или пустой",,
|
||||
"Sent","Отправлено",,
|
||||
"Sent by email","Отправлено по электронной почте",,
|
||||
"Sent date","Дата отправки",,
|
||||
"Server Type","Тип сервера",,
|
||||
"Signature","Подпись",,
|
||||
"Status","Статус",,
|
||||
"Subject","Предмет",,
|
||||
"System","Система",,
|
||||
"TO/CC/BCC recipient's email address is empty","Адрес электронной почты получателя TO/CC/BCC пуст.",,
|
||||
"Target receptor","Целевой рецептор",,
|
||||
"Template","Шаблон",,
|
||||
"Template Context",,,
|
||||
"Template Rules","Шаблоны правил",,
|
||||
"Templates","Шаблоны",,
|
||||
"Test connection","Тестовое соединение",,
|
||||
"The email template model (%s) is different than the entity generating the email (%s)",,,
|
||||
"There is already a default account","Уже есть учетная запись по умолчанию",,
|
||||
"To","К",,
|
||||
"Type","Тип",,
|
||||
"Unable to reach server. Please check Host,Port and SSL/TLS","Невозможно дозвониться до сервера. Пожалуйста, проверьте Host, Port и SSL/TLS.",,
|
||||
"User","Пользователь",,
|
||||
"Valid","Действительный",,
|
||||
"Validate","Подтвердить",,
|
||||
"Waiting model: %s","Модель ожидания: %s",,
|
||||
"Your target receptor is not valid. Please check it.","Ваш целевой рецептор недействителен. Пожалуйста, проверьте.",,
|
||||
"user@mydomain.com","user@mydomain.com",,
|
||||
|
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<csv-inputs xmlns="http://axelor.com/xml/ns/data-import"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/data-import http://axelor.com/xml/ns/data-import/data-import_5.2.xsd">
|
||||
|
||||
<input file="base_role.csv" separator=";" type="com.axelor.auth.db.Role" search="self.name = :name"/>
|
||||
|
||||
<input file="base_permission.csv" separator=";" type="com.axelor.auth.db.Permission" search="self.name = :name" call="com.axelor.csv.script.ImportPermission:importPermissionToRole">
|
||||
<bind to="canRead" eval="can_read == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canWrite" eval="can_write == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canCreate" eval="can_create == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canRemove" eval="can_remove == 'x' ? 'true' : 'false'"/>
|
||||
<bind to="canExport" eval="can_export == 'x' ? 'true' : 'false'"/>
|
||||
</input>
|
||||
|
||||
|
||||
</csv-inputs>
|
||||
@ -0,0 +1,13 @@
|
||||
"name";"object";"can_read";"can_write";"can_create";"can_remove";"can_export";"condition";"conditionParams";"roleName"
|
||||
"perm.message.EmailAddress.r";"com.axelor.apps.message.db.EmailAddress";"x";;;;;;;"Base Read"
|
||||
"perm.message.EmailAccount.r";"com.axelor.apps.message.db.EmailAccount";"x";;;;;;;"Base Read"
|
||||
"perm.message.Message.r";"com.axelor.apps.message.db.Message";"x";;;;;"self.company.id in (?)";"__user__.companySet.id.plus(0)";"Base Read"
|
||||
"perm.message.Template.r";"com.axelor.apps.message.db.Template";"x";;;;;;;"Base Read"
|
||||
"perm.message.EmailAddress.rwc";"com.axelor.apps.message.db.EmailAddress";"x";"x";"x";;;;;"Base User"
|
||||
"perm.message.EmailAccount.rwc";"com.axelor.apps.message.db.EmailAccount";"x";"x";"x";;;;;"Base User"
|
||||
"perm.message.Message.rwc";"com.axelor.apps.message.db.Message";"x";"x";"x";;;"self.company.id in (?)";"__user__.companySet.id.plus(0)";"Base User"
|
||||
"perm.message.Template.rwc";"com.axelor.apps.message.db.Template";"x";"x";"x";;;;;"Base User"
|
||||
"perm.message.EmailAddress.rwcde";"com.axelor.apps.message.db.EmailAddress";"x";"x";"x";"x";"x";;;"Base Manager"
|
||||
"perm.message.EmailAccount.rwcde";"com.axelor.apps.message.db.EmailAccount";"x";"x";"x";"x";"x";;;"Base Manager"
|
||||
"perm.message.Message.rwcde";"com.axelor.apps.message.db.Message";"x";"x";"x";"x";"x";"self.company.id in (?)";"__user__.companySet.id.plus(0)";"Base Manager"
|
||||
"perm.message.Template.rwcde";"com.axelor.apps.message.db.Template";"x";"x";"x";"x";"x";;;"Base Manager"
|
||||
|
@ -0,0 +1,4 @@
|
||||
"name";"description"
|
||||
"Base Read";
|
||||
"Base User";
|
||||
"Base Manager";
|
||||
|
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<grid name="mail-account-grid" title="Mail accounts" model="com.axelor.apps.message.db.EmailAccount">
|
||||
<field name="name"/>
|
||||
<field name="login"/>
|
||||
<field name="host"/>
|
||||
<field name="isDefault"/>
|
||||
</grid>
|
||||
|
||||
<form name="mail-account-form" title="Mail account" model="com.axelor.apps.message.db.EmailAccount"
|
||||
onSave="action-mail-account-method-check-default-mail-account">
|
||||
<panel name="informationsPanel" title="Informations">
|
||||
<field name="name"/>
|
||||
<field name="isDefault" onChange="action-mail-account-method-check-default-mail-account"/>
|
||||
<field name="signature" widget="Html" x-lite="true" height="7" colSpan="12"/>
|
||||
</panel>
|
||||
<panel name="configPanel" title="Configurations" readonlyIf="isValid">
|
||||
<field name="serverTypeSelect" onChange="action-mail-account-onchange-security-select"/>
|
||||
<field name="host"/>
|
||||
<field name="securitySelect" onChange="action-mail-account-onchange-security-select"/>
|
||||
<field name="port"/>
|
||||
</panel>
|
||||
<panel name="loginPanel" title="Login" readonlyIf="isValid" >
|
||||
<field name="login"/>
|
||||
<field name="password" widget="password"/>
|
||||
</panel>
|
||||
<panel name="actionsPanel" sidebar="true">
|
||||
<field name="isValid" readonly="true"/>
|
||||
<button name="testConnectionBtn" onClick="save,action-method-mail-account-validate,save" title="Test connection"/>
|
||||
<spacer name="btnSpacer"/>
|
||||
<button name="fetchEmailsBtn" onClick="save,action-mail-account-metho-fetch-emails" title="Fetch emails" showIf="isValid && serverTypeSelect != null && serverTypeSelect > 1"/>
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
<action-method name="action-method-mail-account-validate">
|
||||
<call class="com.axelor.apps.message.web.MailAccountController" method="validateSmtpAccount"/>
|
||||
</action-method>
|
||||
|
||||
<action-method name="action-mail-account-method-check-default-mail-account">
|
||||
<call class="com.axelor.apps.message.web.MailAccountController" method="checkDefaultMailAccount"/>
|
||||
</action-method>
|
||||
|
||||
<action-method name="action-mail-account-metho-fetch-emails">
|
||||
<call class="com.axelor.apps.message.web.MailAccountController" method="fetchEmails"/>
|
||||
</action-method>
|
||||
|
||||
<action-method name="action-method-mail-account-validate-password">
|
||||
<call class="com.axelor.apps.message.web.MailAccountController" method="validate"/>
|
||||
</action-method>
|
||||
|
||||
<action-attrs name="action-mail-account-onchange-security-select" model="com.axelor.apps.message.db.EmailAccount">
|
||||
<attribute for="port" name="value" expr="#{securitySelect == 1 ? 465 : securitySelect == 2 ? 587 : 25}" if="serverTypeSelect == 1"/>
|
||||
<attribute for="port" name="value" expr="#{securitySelect == 1 ? 995 : 110}" if="serverTypeSelect == 2"/>
|
||||
<attribute for="port" name="value" expr="#{securitySelect == 1 ? 993 : 143}" if="serverTypeSelect == 3"/>
|
||||
</action-attrs>
|
||||
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<grid name="email-address-grid" title="Email addresses" model="com.axelor.apps.message.db.EmailAddress">
|
||||
<toolbar>
|
||||
<button name="checkDuplicateBtn" title="Check Duplicate" onClick="action-base-method-show-duplicate"/>
|
||||
</toolbar>
|
||||
<field name="address"/>
|
||||
</grid>
|
||||
|
||||
<form name="email-address-form" title="Email address" model="com.axelor.apps.message.db.EmailAddress">
|
||||
<panel name="mainPanel" >
|
||||
<field name="address" pattern="^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@+[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$" widget="Email" placeholder="user@mydomain.com" />
|
||||
<field name="partner" if-module="axelor-base" form-view="partner-form" grid-view="partner-grid"/>
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
<form name="email-address-simple-form" title="Email address" model="com.axelor.apps.message.db.EmailAddress">
|
||||
<panel name="mainPanel" >
|
||||
<field name="address" pattern="^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@+[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$" widget="Email" placeholder="user@mydomain.com" />
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
|
||||
<form name="generate-message-wizard-form" model="com.axelor.apps.base.db.Wizard" title="Generate message" onNew="action-generate-message-group-on-new">
|
||||
<panel name="mainPanel" >
|
||||
<field name="_xTemplate" title="Template" widget="SuggestBox" type="MANY_TO_ONE" target="com.axelor.apps.message.db.Template" target-name="name"
|
||||
form-view="template-form" grid-view="template-grid" onSelect="action-method-template-domain"/>
|
||||
<field name="language" title="Language" widget="SuggestBox" type="MANY_TO_ONE" target="com.axelor.apps.base.db.Language" target-name="name"
|
||||
form-view="language-form" grid-view="language-grid" onChange="action-on-change-language-template"/>
|
||||
<spacer name="languageSpacer"/>
|
||||
<button name="validateBtn" title="Validate" onClick="save, action-generate-message-method-generate-message"/>
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
<action-group name="action-generate-message-group-on-new">
|
||||
<action name="action-generate-message-record-on-new"/>
|
||||
<action name="action-method-template-domain"/>
|
||||
</action-group>
|
||||
|
||||
<action-record name="action-generate-message-record-on-new" model="com.axelor.apps.base.db.Wizard">
|
||||
<field name="_xTemplate" expr="eval:__repo__(Template).all().filter('self.metaModel.fullName = ?1 and self.isDefault = true and self.isSystem != true',_templateContextModel).fetchOne()"/>
|
||||
<field name="language" expr="eval:__repo__(Template).all().filter('self.metaModel.fullName = ?1 and self.isDefault = true and self.isSystem != true',_templateContextModel).fetchOne().getLanguage()"
|
||||
if="__repo__(Template).all().filter('self.metaModel.fullName = ?1 and self.isDefault = true and self.isSystem != true',_templateContextModel).fetchOne() != null"/>
|
||||
</action-record>
|
||||
|
||||
<action-method name="action-generate-message-method-generate-message">
|
||||
<call class="com.axelor.apps.message.web.GenerateMessageController" method="generateMessage"/>
|
||||
</action-method>
|
||||
|
||||
<action-attrs name="action-on-change-language-template">
|
||||
<attribute for="_xTemplate" name="value" expr="eval: null"/>
|
||||
</action-attrs>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<menuitem name="mail-conf" title="Message" />
|
||||
|
||||
<menuitem name="mail-conf-template" parent="mail-conf" title="Template" action="admin.root.templating.template" order="5" />
|
||||
|
||||
<action-view name="admin.root.templating.template"
|
||||
title="Template" model="com.axelor.apps.message.db.Template">
|
||||
<view type="grid" name="template-grid"/>
|
||||
<view type="form" name="template-form"/>
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-conf-template-rules" parent="mail-conf" title="Template Rules" action="admin.root.templating.template.rules" order="10" />
|
||||
|
||||
<action-view name="admin.root.templating.template.rules"
|
||||
title="Template Rules" model="com.axelor.apps.base.db.TemplateRule">
|
||||
<view type="grid" name="template-rule-grid" />
|
||||
<view type="form" name="template-rule-form" />
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-root-email-conf-mail-account" parent="mail-conf" title="Email Accounts" action="mail.root.email.conf.mail.account" order="15" />
|
||||
|
||||
<action-view name="mail.root.email.conf.mail.account" title="Email Accounts"
|
||||
model="com.axelor.apps.message.db.EmailAccount" >
|
||||
<view type="grid" />
|
||||
<view type="form" />
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-root-email-conf-email-address" parent="mail-conf" title="Email addresses" action="mail.root.email.conf.email.address" order="20"/>
|
||||
|
||||
<action-view name="mail.root.email.conf.email.address" title="Email addresses"
|
||||
model="com.axelor.apps.message.db.EmailAddress" >
|
||||
<view type="grid" name="email-address-grid"/>
|
||||
<view type="form" name="email-address-form"/>
|
||||
<context name="_duplicateFinderFields" expr="address"/>
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-message" parent="mail-conf" title="All messages" action="mail.root.messages" order="25"/>
|
||||
|
||||
<action-view name="mail.root.messages" title="All messages" model="com.axelor.apps.message.db.Message" >
|
||||
<view type="grid" name="message-grid"/>
|
||||
<view type="form" name="message-form"/>
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-message-not-send" title="Messages not sent" parent="mail-conf" order="26"
|
||||
action="mail.root.messages.not.send"/>
|
||||
|
||||
<action-view name="mail.root.messages.not.send" title="Messages not sent" model="com.axelor.apps.message.db.Message">
|
||||
<view type="grid" name="message-not-sent-grid"/>
|
||||
<view type="form" name="message-form"/>
|
||||
<domain>(self.statusSelect = 1 AND self.sentDateT = null) OR self.statusSelect = 2</domain>
|
||||
</action-view>
|
||||
|
||||
<menuitem name="mail-root-email-conf-routing" parent="mail-conf" title="Routings" action="mail.root.email.conf.routing" order="30" />
|
||||
|
||||
<action-view name="mail.root.email.conf.routing" title="Routings"
|
||||
model="com.axelor.apps.base.db.Routing" >
|
||||
<view type="grid" />
|
||||
<view type="form" />
|
||||
</action-view>
|
||||
|
||||
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<grid name="message-grid" title="Emails" model="com.axelor.apps.message.db.Message" orderBy="-sentDateT">
|
||||
<field name="sentDateT"/>
|
||||
<field name="senderUser" form-view="user-form" grid-view="user-grid"/>
|
||||
<field name="subject"/>
|
||||
</grid>
|
||||
|
||||
<grid name="message-not-sent-grid" title="Emails"
|
||||
model="com.axelor.apps.message.db.Message" orderBy="-sentDateT"
|
||||
canNew="false" canDelete="false" canArchive="false">
|
||||
<toolbar>
|
||||
<button name="regenerateMessageBtn" title="Regenerate messages" onClick="action-message-method-regenerate-messages"/>
|
||||
<button name="resendMessageBtn" title="Resend messages" onClick="action-message-method-send-messages"/>
|
||||
</toolbar>
|
||||
<field name="createdOn"/>
|
||||
<field name="senderUser" form-view="user-form" grid-view="user-grid"/>
|
||||
<field name="subject"/>
|
||||
</grid>
|
||||
|
||||
<form name="message-form" title="Email" model="com.axelor.apps.message.db.Message"
|
||||
onNew="action-group-message-message-onnew">
|
||||
<toolbar>
|
||||
<button name="printBtn" title="Print" icon="fa-print" onClick="save,action-message-method-print-pdf-email" readonlyIf="id == null"/>
|
||||
<button name="sendBtn" title="Send" icon="fa-envelope" onClick="action-group-message-message-send-click" showIf="statusSelect == 1 " />
|
||||
<button name="trashBtn" title="Delete" icon="fa-trash" onClick="action-group-message-message-delete-click" showIf="statusSelect != 4 "/>
|
||||
</toolbar>
|
||||
<panel name="informationsPanel" title="Informations" readonlyIf="statusSelect != 1">
|
||||
<field name="mediaTypeSelect" readonlyIf="statusSelect != 1"/>
|
||||
<field name="statusSelect"/>
|
||||
<field name="senderUser" form-view="user-form" grid-view="user-grid"/>
|
||||
<field name="sentDateT" colSpan="4"/>
|
||||
<panel name="emailAddressPanel" colSpan="12" showIf="mediaTypeSelect == 2">
|
||||
<field name="fromEmailAddress" widget="SuggestBox" grid-view="email-address-grid" form-view="email-address-form"/>
|
||||
<field name="mailAccount" widget="SuggestBox" onChange="action-message-record-get-signature" requiredIf="mediaTypeSelect == 2" grid-view="mail-account-grid" form-view="mail-account-form" domain="self.isValid = true"/>
|
||||
<field name="replyToEmailAddressSet" widget="TagSelect" x-create="address" form-view="email-address-form" colSpan="12" grid-view="email-address-grid" />
|
||||
</panel>
|
||||
</panel>
|
||||
<panel name="recipientAddressPanel" title="Recipient address" readonlyIf="statusSelect != 1" showIf="mediaTypeSelect == 1">
|
||||
<field name="addressBlock" colSpan="12" widget="html" x-lite="false" height="5" showTitle="false" showIf="mediaTypeSelect == 1" requiredIf="mediaTypeSelect == 1"/>
|
||||
</panel>
|
||||
<panel name="recipientsPanel" title="Recipients" readonlyIf="statusSelect != 1" showIf="mediaTypeSelect == 2">
|
||||
<field name="toEmailAddressSet" widget="TagSelect" x-create="address" form-view="email-address-form" colSpan="12" requiredIf="mediaTypeSelect == 2" grid-view="email-address-grid" />
|
||||
<field name="ccEmailAddressSet" widget="TagSelect" x-create="address" form-view="email-address-form" colSpan="12" grid-view="email-address-grid" />
|
||||
<field name="bccEmailAddressSet" widget="TagSelect" x-create="address" form-view="email-address-form" colSpan="12" grid-view="email-address-grid" />
|
||||
</panel>
|
||||
<panel name="messageDestinatedToPanel" title="Message destinated to" readonlyIf="statusSelect != 1" showIf="mediaTypeSelect == 3">
|
||||
<field name="recipientUser" colSpan="6" showTitle="false" showIf="mediaTypeSelect == 3" requiredIf="mediaTypeSelect == 3" form-view="user-form" grid-view="user-grid"/>
|
||||
</panel>
|
||||
<panel name="contentPanel" title="Content" readonlyIf="statusSelect != 1">
|
||||
<field name="subject" title="Subject" colSpan="12" required="true"/>
|
||||
<field name="content" colSpan="12" showTitle="false" widget="html"/>
|
||||
</panel>
|
||||
<panel name="relatedToPanel" title="Related to" sidebar="true" colSpan="12" readonlyIf="statusSelect == 4">
|
||||
<panel name="relatedTo1SelectPanel" colSpan="12">
|
||||
<field name="relatedTo1Select" widget="RefSelect" x-related="relatedTo1SelectId" colSpan="12"/>
|
||||
</panel>
|
||||
<panel name="relatedTo2SelectPanel" colSpan="12">
|
||||
<field name="relatedTo2Select" widget="RefSelect" x-related="relatedTo2SelectId" colSpan="12" showIf="relatedTo1Select != null"/>
|
||||
</panel>
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
<action-group name="action-group-message-message-onnew">
|
||||
<action name="action-message-record-default"/>
|
||||
<action name="action-message-record-mail-account"/>
|
||||
<action name="action-message-record-get-signature"/>
|
||||
<action name="action-message-record-default-media-type"/>
|
||||
</action-group>
|
||||
|
||||
<action-group name="action-group-message-message-send-click">
|
||||
<action name="action-validate-message-content-onsave"/>
|
||||
<action name="save"/>
|
||||
<action name="action-message-method-send-message"/>
|
||||
<action name="save"/>
|
||||
</action-group>
|
||||
|
||||
<action-group name="action-group-message-message-delete-click">
|
||||
<action name="save"/>
|
||||
<action name="action-message-record-delete-status"/>
|
||||
<action name="save"/>
|
||||
</action-group>
|
||||
|
||||
<action-record name="action-message-record-default-media-type" model="com.axelor.apps.message.db.Message">
|
||||
<field name="mediaTypeSelect" expr="eval:defaultMediaType"/>
|
||||
<field name="mediaTypeSelect" expr="eval: _mediaTypeSelect" if="_mediaTypeSelect"/>
|
||||
</action-record>
|
||||
|
||||
<action-record name="action-message-record-default" model="com.axelor.apps.message.db.Message">
|
||||
<field name="senderUser" expr="eval:__user__"/>
|
||||
<field name="relatedTo1Select" expr="eval: _templateContextModel" if="_templateContextModel"/>
|
||||
<field name="relatedTo1SelectId" expr="eval: Long.parseLong(_objectId)" if="_objectId"/>
|
||||
</action-record>
|
||||
|
||||
<action-record name="action-message-record-mail-account" model="com.axelor.apps.message.db.Message">
|
||||
<field name="mailAccount" expr="eval: __repo__(EmailAccount).all().filter('self.isDefault = true and self.user = ?1',senderUser).fetchOne()" if="__config__.app.getApp('base').getEmailAccountByUser()"/>
|
||||
<field name="mailAccount" expr="eval: __repo__(EmailAccount).all().filter('self.isDefault = true').fetchOne()" if="!__config__.app.getApp('base').getEmailAccountByUser()"/>
|
||||
</action-record>
|
||||
|
||||
<action-record name="action-message-record-get-signature" model="com.axelor.apps.message.db.Message">
|
||||
<field name="content" expr="eval: '<p></p><p></p>' + mailAccount?.signature" if="content == null && mailAccount?.signature != null"/>
|
||||
</action-record>
|
||||
|
||||
<action-record name="action-message-record-delete-status" model="com.axelor.apps.message.db.Message">
|
||||
<field name="statusSelect" expr="4"/>
|
||||
</action-record>
|
||||
|
||||
|
||||
<!-- ACTION METHOD -->
|
||||
<action-method name="action-message-method-send-message">
|
||||
<call class="com.axelor.apps.message.web.MessageController" method="sendMessage"/>
|
||||
</action-method>
|
||||
|
||||
<action-method name="action-message-method-send-messages">
|
||||
<call class="com.axelor.apps.message.web.MessageController" method="sendMessages"/>
|
||||
</action-method>
|
||||
|
||||
<action-method name="action-message-method-regenerate-messages">
|
||||
<call class="com.axelor.apps.message.web.MessageController" method="regenerateMessages"/>
|
||||
</action-method>
|
||||
|
||||
<!-- Common action for all messages sent by email using a template and the context -->
|
||||
|
||||
<action-method name="action-send-by-email-with-template">
|
||||
<call class="com.axelor.apps.message.web.GenerateMessageController" method="callMessageWizard"/>
|
||||
</action-method>
|
||||
|
||||
<action-validate name="action-validate-message-content-onsave">
|
||||
<alert message="No Mail content entered." if="mediaTypeSelect == 1 && content== null"/>
|
||||
</action-validate>
|
||||
|
||||
<action-view name="action.message.view.messages"
|
||||
model="com.axelor.apps.message.db.Message"
|
||||
title="Mail">
|
||||
<view name="message-grid" type="grid"/>
|
||||
<view name="message-form" type="form"/>
|
||||
<domain>
|
||||
self.relatedTo1SelectId = :relatedToSelectId
|
||||
AND self.relatedTo1Select = :relatedToSelect
|
||||
OR self.relatedTo2SelectId = :relatedToSelectId
|
||||
AND self.relatedTo2Select = :relatedToSelect
|
||||
</domain>
|
||||
<context name="relatedToSelectId" expr="eval: id"/>
|
||||
<context name="relatedToSelect"
|
||||
expr="eval: _model"/>
|
||||
</action-view>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<!-- Nomenclature : * name : "interfaceName" + "fieldName" + ".select" -->
|
||||
|
||||
<selection name="message.related.to.select">
|
||||
<option value="com.axelor.auth.db.Group">Group</option>
|
||||
<option value="com.axelor.auth.db.User">User</option>
|
||||
</selection>
|
||||
|
||||
<selection name="message.type.select">
|
||||
<option value="1">Received</option>
|
||||
<option value="2">Sent</option>
|
||||
</selection>
|
||||
|
||||
<selection name="message.status.select">
|
||||
<option value="1">Draft</option>
|
||||
<option value="2">In progress</option>
|
||||
<option value="3">Sent</option>
|
||||
<option value="4">Deleted</option>
|
||||
</selection>
|
||||
|
||||
<selection name="mail.account.server.type.select">
|
||||
<option value="1">SMTP</option>
|
||||
<option value="2">POP</option>
|
||||
<option value="3">IMAP</option>
|
||||
</selection>
|
||||
|
||||
<selection name="message.media.type.select">
|
||||
<option value="1">Mail</option>
|
||||
<option value="2">Email</option>
|
||||
<option value="3">Chat</option>
|
||||
</selection>
|
||||
|
||||
<selection name="template.media.type.select">
|
||||
<option value="1">Mail</option>
|
||||
<option value="2">Email</option>
|
||||
<option value="3">Chat</option>
|
||||
</selection>
|
||||
|
||||
<selection name="mail.account.security.select">
|
||||
<option value="0">NONE</option>
|
||||
<option value="1">SSL</option>
|
||||
<option value="2">STARTTLS</option>
|
||||
</selection>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<grid name="template-grid" title="Templates" model="com.axelor.apps.message.db.Template">
|
||||
<field name="name"/>
|
||||
<field name="subject"/>
|
||||
<field name="metaModel" form-view="meta-model-form" grid-view="meta-model-grid"/>
|
||||
<field name="mediaTypeSelect"/>
|
||||
</grid>
|
||||
|
||||
<form name="template-form" title="Template" model="com.axelor.apps.message.db.Template"
|
||||
onNew="action-template-record-new" width="large">
|
||||
<panel name="mainPanel" colSpan="12">
|
||||
<field name="name" colSpan="4"/>
|
||||
<field name="mediaTypeSelect" colSpan="4"/>
|
||||
<field name="isDefault" colSpan="2"/>
|
||||
<field name="isSystem" colSpan="2"/>
|
||||
<field name="isJson" onChange="action-template-record-is-json-change"/>
|
||||
<field name="metaModel" hideIf="isJson" form-view="meta-model-form" grid-view="meta-model-grid"/>
|
||||
<field name="metaJsonModel" showIf="isJson" form-view="json-model-form" grid-view="json-model-grid" />
|
||||
<field name="target"/>
|
||||
</panel>
|
||||
<panel name="recipientAddressPanel" title="Recipient address" showIf="mediaTypeSelect == 1">
|
||||
<field name="addressBlock" colSpan="12" widget="html" x-lite="false" height="5" showTitle="false"/>
|
||||
</panel>
|
||||
<panel name="fromPanel" title="From" showIf="mediaTypeSelect == 2 || mediaTypeSelect == 4">
|
||||
<field name="fromAdress" height="2" colSpan="12"/>
|
||||
</panel>
|
||||
<panel name="replyToPanel" title="Reply to" showIf="mediaTypeSelect == 2 || mediaTypeSelect == 4">
|
||||
<field name="replyToRecipients" height="1" colSpan="12"/>
|
||||
</panel>
|
||||
<panel name="recipientsPanel" title="Recipients" showIf="mediaTypeSelect == 2 || mediaTypeSelect == 4">
|
||||
<field name="toRecipients" height="2" colSpan="12"/>
|
||||
<field name="ccRecipients" height="2" colSpan="12"/>
|
||||
<field name="bccRecipients" height="2" colSpan="12"/>
|
||||
</panel>
|
||||
<panel-tabs name="mainPanelTab">
|
||||
<panel name="subjectContentPanel" title="Content" colSpan="12">
|
||||
<field name="subject" colSpan="12" height="2"/>
|
||||
<field name="content" showTitle="false" widget="html" colSpan="12"/>
|
||||
</panel>
|
||||
<panel-dashlet name="templateMessagePanel" action="template.messages.by.template" title="Messages"/>
|
||||
</panel-tabs>
|
||||
<panel-related name="templateContextPanel" field="templateContextList" colSpan="12"/>
|
||||
</form>
|
||||
|
||||
<action-record name="action-template-record-new" model="com.axelor.apps.message.db.Template">
|
||||
<field name="metaModel" expr="eval: _parent?.targetSelect == 1 ? __repo__(MetaModel).all().filter('self.name = \'Partner\'').fetchOne() : (_parent?.targetSelect == 2 ? __repo__(MetaModel).all().filter('self.name = \'Lead\'').fetchOne() : null)" if="_parent?.targetSelect"/>
|
||||
<field name="metaModel" expr="eval: _parent?.metaModel" if="_parent?.metaModel"/>
|
||||
<field name="metaModel" expr="eval: _parent?._parent?.metaModel" if="_parent?._parent?.metaModel"/>
|
||||
<field if="_mediaType != null" name="mediaTypeSelect" expr="eval:_mediaType"/>
|
||||
</action-record>
|
||||
|
||||
<action-record name="action-template-record-is-json-change" model="com.axelor.apps.message.db.Template">
|
||||
<field name="metaModel" expr="eval:null"/>
|
||||
<field name="metaJsonModel" expr="eval:null"/>
|
||||
</action-record>
|
||||
|
||||
<action-view name="template.messages.by.template" title="All messages" model="com.axelor.apps.message.db.Message" >
|
||||
<view type="grid" name="message-grid"/>
|
||||
<view type="form" name="message-form"/>
|
||||
<domain>self.template.id = :template</domain>
|
||||
<context name="template" expr="eval: id"/>
|
||||
</action-view>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<object-views xmlns="http://axelor.com/xml/ns/object-views"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://axelor.com/xml/ns/object-views http://axelor.com/xml/ns/object-views/object-views_5.2.xsd">
|
||||
|
||||
<grid name="template-context-grid" title="Template Context" model="com.axelor.apps.message.db.TemplateContext" editable="true">
|
||||
<field name="name" width="200"/>
|
||||
<field name="value"/>
|
||||
</grid>
|
||||
|
||||
<form name="template-context-form" title="Template Context" model="com.axelor.apps.message.db.TemplateContext" width="large">
|
||||
<panel name="mainPanel" colSpan="12">
|
||||
<field name="name" colSpan="4"/>
|
||||
<field name="value" colSpan="8"/>
|
||||
</panel>
|
||||
</form>
|
||||
|
||||
</object-views>
|
||||
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Axelor Business Solutions
|
||||
*
|
||||
* Copyright (C) 2019 Axelor (<http://axelor.com>).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.axelor.apps.message.mail;
|
||||
|
||||
import com.axelor.db.JpaModule;
|
||||
import com.google.inject.AbstractModule;
|
||||
|
||||
public class MyModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new JpaModule("testUnit", true, true));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user