com.aoindustries.aoserv.master.EmailHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aoserv-master Show documentation
Show all versions of aoserv-master Show documentation
Master server for the AOServ Platform.
/*
* aoserv-master - Master server for the AOServ Platform.
* Copyright (C) 2001-2013, 2015, 2017, 2018, 2019, 2020 AO Industries, Inc.
* [email protected]
* 7262 Bull Pen Cir
* Mobile, AL 36695
*
* This file is part of aoserv-master.
*
* aoserv-master is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aoserv-master 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with aoserv-master. If not, see .
*/
package com.aoindustries.aoserv.master;
import com.aoindustries.aoserv.client.AOServObject;
import com.aoindustries.aoserv.client.account.Account;
import com.aoindustries.aoserv.client.email.InboxAttributes;
import com.aoindustries.aoserv.client.email.List;
import com.aoindustries.aoserv.client.email.MajordomoList;
import com.aoindustries.aoserv.client.email.MajordomoServer;
import com.aoindustries.aoserv.client.email.SmtpRelay;
import com.aoindustries.aoserv.client.email.SpamMessage;
import com.aoindustries.aoserv.client.linux.Group;
import com.aoindustries.aoserv.client.linux.GroupType;
import com.aoindustries.aoserv.client.linux.PosixPath;
import com.aoindustries.aoserv.client.linux.UserType;
import com.aoindustries.aoserv.client.master.User;
import com.aoindustries.aoserv.client.master.UserHost;
import com.aoindustries.aoserv.client.schema.Table;
import com.aoindustries.aoserv.daemon.client.AOServDaemonConnector;
import com.aoindustries.collections.IntList;
import com.aoindustries.dbc.DatabaseAccess;
import com.aoindustries.dbc.DatabaseConnection;
import com.aoindustries.io.stream.StreamableOutput;
import com.aoindustries.net.DomainName;
import com.aoindustries.net.Email;
import com.aoindustries.net.HostAddress;
import com.aoindustries.validation.ValidationException;
import com.aoindustries.validation.ValidationResult;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The EmailHandler
handles all the accesses to the email tables.
*
* @author AO Industries, Inc.
*/
final public class EmailHandler {
private static final Logger logger = Logger.getLogger(EmailHandler.class.getName());
private EmailHandler() {
}
private final static Map disabledLists = new HashMap<>();
private final static Map disabledPipes = new HashMap<>();
private final static Map disabledSmtpRelays = new HashMap<>();
public static boolean canAccessDomain(DatabaseConnection conn, RequestSource source, int domain) throws IOException, SQLException {
User mu = MasterServer.getUser(conn, source.getCurrentAdministrator());
if(mu!=null) {
if(MasterServer.getUserHosts(conn, source.getCurrentAdministrator()).length!=0) {
return NetHostHandler.canAccessHost(conn, source, getLinuxServerForDomain(conn, domain));
} else {
return true;
}
} else {
return PackageHandler.canAccessPackage(conn, source, getPackageForDomain(conn, domain));
}
}
public static void checkAccessDomain(DatabaseConnection conn, RequestSource source, String action, int domain) throws IOException, SQLException {
User mu = MasterServer.getUser(conn, source.getCurrentAdministrator());
if(mu!=null) {
if(MasterServer.getUserHosts(conn, source.getCurrentAdministrator()).length!=0) {
NetHostHandler.checkAccessHost(conn, source, action, getLinuxServerForDomain(conn, domain));
}
} else {
PackageHandler.checkAccessPackage(conn, source, action, getPackageForDomain(conn, domain));
}
}
public static void checkAccessSmtpRelay(DatabaseConnection conn, RequestSource source, String action, int smtpRelay) throws IOException, SQLException {
User mu = MasterServer.getUser(conn, source.getCurrentAdministrator());
if(mu!=null) {
if(MasterServer.getUserHosts(conn, source.getCurrentAdministrator()).length!=0) {
NetHostHandler.checkAccessHost(conn, source, action, getLinuxServerForSmtpRelay(conn, smtpRelay));
}
} else {
PackageHandler.checkAccessPackage(conn, source, action, getPackageForSmtpRelay(conn, smtpRelay));
}
}
public static void checkAccessAddress(DatabaseConnection conn, RequestSource source, String action, int address) throws IOException, SQLException {
checkAccessDomain(conn, source, action, getDomainForAddress(conn, address));
}
public static void checkAccessList(DatabaseConnection conn, RequestSource source, String action, int list) throws IOException, SQLException {
LinuxAccountHandler.checkAccessGroupServer(conn, source, action, getLinuxGroupServerForList(conn, list));
}
public static void checkAccessListPath(DatabaseConnection conn, RequestSource source, String action, int linuxServer, PosixPath path) throws IOException, SQLException {
if(
!List.isValidRegularPath(
path,
NetHostHandler.getOperatingSystemVersionForHost(conn, linuxServer)
)
) {
String pathStr = path.toString();
// Can also be a path in a majordomo server that they may access
if(pathStr.startsWith(MajordomoServer.MAJORDOMO_SERVER_DIRECTORY.toString()+'/')) {
int pos=pathStr.indexOf('/', MajordomoServer.MAJORDOMO_SERVER_DIRECTORY.toString().length()+1);
if(pos!=-1) {
String domain=pathStr.substring(MajordomoServer.MAJORDOMO_SERVER_DIRECTORY.toString().length()+1, pos);
pathStr=pathStr.substring(pos+1);
if(pathStr.startsWith("lists/")) {
String listName=pathStr.substring(6);
if(MajordomoList.isValidListName(listName)) {
int ed=getDomain(conn, linuxServer, domain);
checkAccessMajordomoServer(conn, source, action, getMajordomoServer(conn, ed));
return;
}
}
}
}
String message="email.List.path="+path+" not allowed, '"+action+"'";
throw new SQLException(message);
}
}
public static void checkAccessPipe(DatabaseConnection conn, RequestSource source, String action, int pipe) throws IOException, SQLException {
User mu = MasterServer.getUser(conn, source.getCurrentAdministrator());
if(mu!=null) {
if(MasterServer.getUserHosts(conn, source.getCurrentAdministrator()).length!=0) {
NetHostHandler.checkAccessHost(conn, source, action, getLinuxServerForPipe(conn, pipe));
}
} else {
PackageHandler.checkAccessPackage(conn, source, action, getPackageForPipe(conn, pipe));
}
}
public static void checkAccessPipeCommand(
DatabaseConnection conn,
RequestSource source,
String action,
String path
) throws IOException, SQLException {
throw new SQLException("Method not implemented.");
}
public static void checkAccessMajordomoServer(DatabaseConnection conn, RequestSource source, String action, int majordomoServer) throws IOException, SQLException {
checkAccessDomain(conn, source, action, majordomoServer);
}
public static int addAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
String address,
int domain
) throws IOException, SQLException {
checkAccessDomain(conn, source, "addAddress", domain);
return addAddress0(conn, invalidateList, address, domain);
}
private static int addAddress0(
DatabaseConnection conn,
InvalidateList invalidateList,
String address,
int domain
) throws IOException, SQLException {
{
ValidationResult result = Email.validate(
address,
getNetDomainForDomain(conn, domain)
);
if(!result.isValid()) throw new SQLException("Invalid email address: " + result);
}
int address_id = conn.executeIntUpdate(
"INSERT INTO email.\"Address\" (address, \"domain\") VALUES (?,?) RETURNING id",
address,
domain
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_ADDRESSES,
getAccountForAddress(conn, address_id),
getLinuxServerForAddress(conn, address_id),
false
);
return address_id;
}
public static int addForwarding(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address,
Email destination
) throws IOException, SQLException {
String destinationStr = destination.toString();
if(destinationStr.toLowerCase().endsWith("@comcast.net")) throw new SQLException(
"We no longer allow forwarding to comcast accounts. Comcast blocks mail servers\n"
+ "that forward spam originating from other networks. Our spam filters are\n"
+ "associated with email inboxes, not forwarding settings. Our forwarding\n"
+ "configuration assumes the final recipient account will provide spam filters.\n"
+ "Also, our spam filters rely heavily on feedback from the mail client, and\n"
+ "this feedback is not available from forwarded email. For this reason we\n"
+ "will not provide filters on the forwarded email.\n"
+ "\n"
+ "Please create an email inbox, associate your email address with the inbox and\n"
+ "obtain your email directly from our mail servers over POP3 or IMAP instead of\n"
+ "forwarding to comcast.net.\n"
+ "\n"
+ "Sorry for any inconvenience, but Comcast's unprecedented blocking policy and\n"
+ "our standard installation of SpamAssassin filters are not compatible.\n"
);
checkAccessAddress(conn, source, "addForwarding", address);
int forwarding = conn.executeIntUpdate(
"INSERT INTO email.\"Forwarding\" (email_address, destination) VALUES (?,?) RETURNING id",
address,
AOServObject.USE_SQL_DATA_WRITE ? destination : destinationStr
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_FORWARDING,
getAccountForAddress(conn, address),
getLinuxServerForAddress(conn, address),
false
);
return forwarding;
}
public static int addList(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
PosixPath path,
int userServer,
int groupServer
) throws IOException, SQLException {
checkAccessListPath(conn, source, "addList", LinuxAccountHandler.getServerForUserServer(conn, userServer), path);
// Allow the mail user
com.aoindustries.aoserv.client.linux.User.Name user = LinuxAccountHandler.getUserForUserServer(conn, userServer);
if(!user.equals(com.aoindustries.aoserv.client.linux.User.MAIL)) LinuxAccountHandler.checkAccessUserServer(conn, source, "addList", userServer);
// Check the group
LinuxAccountHandler.checkAccessGroupServer(conn, source, "addList", groupServer);
return addList0(
conn,
invalidateList,
path,
userServer,
groupServer
);
}
private static int addList0(
DatabaseConnection conn,
InvalidateList invalidateList,
PosixPath path,
int linuxUserServer,
int linuxGroupServer
) throws IOException, SQLException {
if(LinuxAccountHandler.isUserServerDisabled(conn, linuxUserServer)) throw new SQLException("Unable to add List, UserServer disabled: "+linuxUserServer);
Account.Name packageName=LinuxAccountHandler.getPackageForGroupServer(conn, linuxGroupServer);
if(PackageHandler.isPackageDisabled(conn, packageName)) throw new SQLException("Unable to add List, Package disabled: "+packageName);
// The server for both account and group must be the same
int userServer_linuxServer = LinuxAccountHandler.getServerForUserServer(conn, linuxUserServer);
int groupServer_linuxServer = LinuxAccountHandler.getServerForGroupServer(conn, linuxGroupServer);
if(userServer_linuxServer!=groupServer_linuxServer) throw new SQLException("(linux.UserServer.id="+linuxUserServer+").ao_server!=(linux.GroupServer.id="+linuxGroupServer+").ao_server");
// Must not already have this path on this server
if(
conn.executeBooleanQuery(
"select\n"
+ " (\n"
+ " select\n"
+ " el.id\n"
+ " from\n"
+ " email.\"List\" el,\n"
+ " linux.\"GroupServer\" lsg\n"
+ " where\n"
+ " el.path=?\n"
+ " and el.linux_server_group=lsg.id\n"
+ " and lsg.ao_server=?\n"
+ " limit 1\n"
+ " ) is not null",
path,
groupServer_linuxServer
)
) throw new SQLException("List path already used: "+path+" on "+groupServer_linuxServer);
int list = conn.executeIntUpdate(
"INSERT INTO email.\"List\" (\n"
+ " \"path\",\n"
+ " linux_server_account,\n"
+ " linux_server_group\n"
+ "values(\n"
+ " ?,\n"
+ " ?,\n"
+ " ?\n"
+ ") RETURNING id",
path,
linuxUserServer,
linuxGroupServer
);
// Create the empty list file
int uid = LinuxAccountHandler.getUidForUserServer(conn, linuxUserServer);
int gid = LinuxAccountHandler.getGidForGroupServer(conn, linuxGroupServer);
int mode = path.toString().startsWith(MajordomoServer.MAJORDOMO_SERVER_DIRECTORY.toString() + '/') ? 0644 : 0640;
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(conn, userServer_linuxServer);
conn.releaseConnection();
daemonConnector.setEmailListFile(path, "", uid, gid, mode);
// Notify all clients of the update
invalidateList.addTable(conn,
Table.TableID.EMAIL_LISTS,
InvalidateList.allAccounts,
userServer_linuxServer,
false
);
return list;
}
public static int addListAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address,
int list
) throws IOException, SQLException {
checkAccessAddress(conn, source, "addListAddress", address);
checkAccessList(conn, source, "addListAddress", list);
return addListAddress0(
conn,
invalidateList,
address,
list
);
}
private static int addListAddress0(
DatabaseConnection conn,
InvalidateList invalidateList,
int address,
int list
) throws IOException, SQLException {
// The email_domain and the email_list must be on the same server
int domainLinuxServer = getLinuxServerForAddress(conn, address);
int list_linuxServer = getLinuxServerForList(conn, list);
if(domainLinuxServer != list_linuxServer) throw new SQLException("List server ("+list_linuxServer+")!=Email address server ("+domainLinuxServer+')');
int listAddress = conn.executeIntUpdate(
"INSERT INTO email.\"ListAddress\" (email_address, email_list) VALUES (?,?) RETURNING id",
address,
list
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_LIST_ADDRESSES,
getAccountForAddress(conn, address),
getLinuxServerForAddress(conn, address),
false
);
return listAddress;
}
/**
* Adds an email pipe.
*/
public static int addPipe(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int linuxServer,
String command,
Account.Name packageName
) throws IOException, SQLException {
NetHostHandler.checkAccessHost(conn, source, "addPipe", linuxServer);
checkAccessPipeCommand(conn, source, "addPipe", command);
PackageHandler.checkAccessPackage(conn, source, "addPipe", packageName);
PackageHandler.checkPackageAccessHost(conn, source, "addPipe", packageName, linuxServer);
return addPipe0(
conn,
invalidateList,
linuxServer,
command,
packageName
);
}
private static int addPipe0(
DatabaseConnection conn,
InvalidateList invalidateList,
int linuxServer,
String command,
Account.Name packageName
) throws IOException, SQLException {
if(PackageHandler.isPackageDisabled(conn, packageName)) throw new SQLException("Unable to add Pipe, Package disabled: "+packageName);
int pipe = conn.executeIntUpdate("INSERT INTO email.\"Pipe\" VALUES (default,?,?,?,null) RETURNING id", linuxServer, command, packageName);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_PIPES,
PackageHandler.getAccountForPackage(conn, packageName),
linuxServer,
false
);
return pipe;
}
public static int addPipeAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address,
int pipe
) throws IOException, SQLException {
checkAccessAddress(conn, source, "addPipeAddress", address);
checkAccessPipe(conn, source, "addPipeAddress", pipe);
return addPipeAddress0(
conn,
invalidateList,
address,
pipe
);
}
private static int addPipeAddress0(
DatabaseConnection conn,
InvalidateList invalidateList,
int address,
int pipe
) throws IOException, SQLException {
int pipeAddress = conn.executeIntUpdate("INSERT INTO email.\"PipeAddress\" VALUES (default,?,?) RETURNING id", address, pipe);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_PIPE_ADDRESSES,
getAccountForAddress(conn, address),
getLinuxServerForAddress(conn, address),
false
);
return pipeAddress;
}
public static int addInboxAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address,
int userServer
) throws IOException, SQLException {
checkAccessAddress(conn, source, "addInboxAddress", address);
LinuxAccountHandler.checkAccessUserServer(conn, source, "addInboxAddress", userServer);
com.aoindustries.aoserv.client.linux.User.Name user = LinuxAccountHandler.getUserForUserServer(conn, userServer);
if(user.equals(com.aoindustries.aoserv.client.linux.User.MAIL)) throw new SQLException("Not allowed to add email addresses to User named '"+com.aoindustries.aoserv.client.linux.User.MAIL+'\'');
// TODO: Make sure they are on the same server
int inboxAddress = conn.executeIntUpdate("INSERT INTO email.\"InboxAddress\" VALUES (default,?,?) RETURNING id", address, userServer);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.LINUX_ACC_ADDRESSES,
getAccountForAddress(conn, address),
getLinuxServerForAddress(conn, address),
false
);
return inboxAddress;
}
public static int addDomain(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
DomainName netDomain,
int linuxServer,
Account.Name packageName
) throws IOException, SQLException {
MasterServer.checkAccessHostname(conn, source, "addDomain", netDomain.toString());
NetHostHandler.checkAccessHost(conn, source, "addDomain", linuxServer);
PackageHandler.checkAccessPackage(conn, source, "addDomain", packageName);
PackageHandler.checkPackageAccessHost(conn, source, "addDomain", packageName, linuxServer);
int domain = conn.executeIntUpdate("INSERT INTO email.\"Domain\" VALUES (default,?,?,?) RETURNING id", netDomain, linuxServer, packageName);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_DOMAINS,
PackageHandler.getAccountForPackage(conn, packageName),
linuxServer,
false
);
return domain;
}
/**
* Adds a email SMTP relay.
*/
public static int addSmtpRelay(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
Account.Name packageName,
int linuxServer,
HostAddress host,
String type,
long duration
) throws IOException, SQLException {
// Only master users can add relays
User mu=MasterServer.getUser(conn, source.getCurrentAdministrator());
if(mu==null) throw new SQLException("Only master users may add SMTP relays.");
PackageHandler.checkAccessPackage(conn, source, "addSmtpRelay", packageName);
if(linuxServer==-1) {
if(MasterServer.getUserHosts(conn, source.getCurrentAdministrator()).length!=0) throw new SQLException("Only super-users may add global SMTP relays.");
} else {
NetHostHandler.checkAccessHost(conn, source, "addSmtpRelay", linuxServer);
PackageHandler.checkPackageAccessHost(conn, source, "addSmtpRelay", packageName, linuxServer);
}
if(duration!=-1 && duration<=0) throw new SQLException("Duration must be positive: "+duration);
if(PackageHandler.isPackageDisabled(conn, packageName)) throw new SQLException("Unable to add SmtpRelay, Package disabled: "+packageName);
int smtpRelay;
if(linuxServer == -1) {
smtpRelay = conn.executeIntUpdate(
"INSERT INTO email.\"SmtpRelay\" values(default,?,null,?,?,now(),now(),0,?,null) RETURNING id",
packageName,
host,
type,
duration == -1 ? DatabaseAccess.Null.TIMESTAMP : new Timestamp(System.currentTimeMillis() + duration) // TODO: Timestamp nanosecond precision
);
} else {
smtpRelay = conn.executeIntUpdate(
"INSERT INTO email.\"SmtpRelay\" VALUES (default,?,?,?,?,now(),now(),0,?,null) RETURNING id",
packageName,
linuxServer,
host,
type,
duration == -1 ? DatabaseAccess.Null.TIMESTAMP : new Timestamp(System.currentTimeMillis() + duration) // TODO: Timestamp nanosecond precision
);
}
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_SMTP_RELAYS,
PackageHandler.getAccountForPackage(conn, packageName),
linuxServer,
false
);
return smtpRelay;
}
/**
* Only report each error at most once per 12 hours per package.
*/
private static final long SMTP_STAT_REPORT_INTERVAL=12L*60*60*1000;
private static final Map smtpStatLastReports=new HashMap<>();
public static int addSpamMessage(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int smtpRelay,
String message
) throws IOException, SQLException {
com.aoindustries.aoserv.client.account.User.Name currentAdministrator = source.getCurrentAdministrator();
User masterUser=MasterServer.getUser(conn, currentAdministrator);
UserHost[] masterServers=masterUser==null?null:MasterServer.getUserHosts(conn, currentAdministrator);
if(masterUser==null || masterServers.length!=0) throw new SQLException("Only master users may add spam email messages.");
int spamMessage = conn.executeIntUpdate(
"INSERT INTO email.\"SpamMessage\" VALUES(default,?,now(),?) RETURNING id",
smtpRelay,
message
);
// Notify all clients of the update
invalidateList.addTable(conn,
Table.TableID.SPAM_EMAIL_MESSAGES,
InvalidateList.allAccounts,
InvalidateList.allHosts,
false
);
return spamMessage;
}
public static int addMajordomoList(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int majordomoServer,
String listName
) throws IOException, SQLException {
if(!MajordomoList.isValidListName(listName)) throw new SQLException("Invalide Majordomo list name: "+listName);
checkAccessMajordomoServer(conn, source, "addMajordomoList", majordomoServer);
DomainName domainName=getNetDomainForDomain(conn, majordomoServer);
PosixPath msPath;
PosixPath listPath;
PosixPath infoPath;
PosixPath introPath;
try {
msPath = PosixPath.valueOf(MajordomoServer.MAJORDOMO_SERVER_DIRECTORY+"/"+domainName);
listPath = PosixPath.valueOf(msPath+"/lists/"+listName);
infoPath = PosixPath.valueOf(listPath+".info");
introPath = PosixPath.valueOf(listPath+".intro");
} catch(ValidationException e) {
throw new SQLException(e);
}
int linuxServer = getLinuxServerForDomain(conn, majordomoServer);
// Disabled checks
Account.Name packageName=getPackageForDomain(conn, majordomoServer);
if(PackageHandler.isPackageDisabled(conn, packageName)) throw new SQLException("Unable to add Majordomo list, Package for Majordomo server #"+majordomoServer+" is disabled: "+packageName);
// Find the email addresses
int ownerListnameAddress=getOrAddAddress(conn, invalidateList, "owner-"+listName, majordomoServer);
int listnameOwnerAddress=getOrAddAddress(conn, invalidateList, listName+"-owner", majordomoServer);
int listnameApprovalAddress=getOrAddAddress(conn, invalidateList, listName+"-approval", majordomoServer);
// Add the email list
int lsa=getLinuxUserServerForMajordomoServer(conn, majordomoServer);
int lsg=getLinuxGroupServerForMajordomoServer(conn, majordomoServer);
int list = addList0(
conn,
invalidateList,
listPath,
lsa,
lsg
);
// Add the listname email pipe and address
int listnamePipe=addPipe0(
conn,
invalidateList,
linuxServer,
msPath+"/wrapper resend -l "+listName+' '+listName+"-list@"+domainName,
packageName
);
int listnameAddress=getOrAddAddress(conn, invalidateList, listName, majordomoServer);
int listnamePipeAddress=addPipeAddress0(conn, invalidateList, listnameAddress, listnamePipe);
// Add the listname-list email list address
int listnameListAddress=getOrAddAddress(conn, invalidateList, listName+"-list", majordomoServer);
int listnameListListAddress=addListAddress0(conn, invalidateList, listnameListAddress, list);
// Add the listname-request email pipe and address
int listnameRequestPipe=addPipe0(
conn,
invalidateList,
linuxServer,
msPath+"/wrapper majordomo -l "+listName,
packageName
);
int listnameRequestAddress=getOrAddAddress(conn, invalidateList, listName+"-request", majordomoServer);
int listnameRequestPipeAddress=addPipeAddress0(conn, invalidateList, listnameRequestAddress, listnameRequestPipe);
// Add the majordomo_list
conn.executeUpdate(
"insert into email.\"MajordomoList\" values(?,?,?,?,?,?,?,?,?)",
list,
majordomoServer,
listName,
listnamePipeAddress,
listnameListListAddress,
ownerListnameAddress,
listnameOwnerAddress,
listnameApprovalAddress,
listnameRequestPipeAddress
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.MAJORDOMO_LISTS,
PackageHandler.getAccountForPackage(conn, packageName),
linuxServer,
false
);
// Create the empty info and intro files
String file = MajordomoList.getDefaultInfoFile(domainName, listName);
String introFile = MajordomoList.getDefaultIntroFile(domainName, listName);
int uid = LinuxAccountHandler.getUidForUserServer(conn, lsa);
int gid = LinuxAccountHandler.getGidForGroupServer(conn, lsg);
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(conn, linuxServer);
conn.releaseConnection();
daemonConnector.setEmailListFile(infoPath, file, uid, gid, 0664);
daemonConnector.setEmailListFile(introPath, introFile, uid, gid, 0664);
return list;
}
public static void addMajordomoServer(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int domain,
int userServer,
int groupServer,
String version
) throws IOException, SQLException {
// Security checks
checkAccessDomain(conn, source, "addMajordomoServer", domain);
LinuxAccountHandler.checkAccessUserServer(conn, source, "addMajordomoServer", userServer);
com.aoindustries.aoserv.client.linux.User.Name lsaUsername=LinuxAccountHandler.getUserForUserServer(conn, userServer);
if(lsaUsername.equals(com.aoindustries.aoserv.client.linux.User.MAIL)) throw new SQLException("Unable to add MajordomoServer with UserServer of '"+lsaUsername+'\'');
String lsaType=LinuxAccountHandler.getTypeForUserServer(conn, userServer);
if(
!lsaType.equals(UserType.APPLICATION)
&& !lsaType.equals(UserType.USER)
) throw new SQLException("May only add Majordomo servers using Linux accounts of type '"+UserType.APPLICATION+"' or '"+UserType.USER+"', trying to use '"+lsaType+'\'');
LinuxAccountHandler.checkAccessGroupServer(conn, source, "addMajordomoServer", groupServer);
Group.Name lsgName=LinuxAccountHandler.getGroupForGroupServer(conn, groupServer);
if(
lsgName.equals(Group.FTPONLY)
|| lsgName.equals(Group.MAIL)
|| lsgName.equals(Group.MAILONLY)
) throw new SQLException("Unable to add MajordomoServer with GroupServer of '"+lsgName+'\'');
String lsgType=LinuxAccountHandler.getTypeForGroupServer(conn, groupServer);
if(
!lsgType.equals(GroupType.APPLICATION)
&& !lsgType.equals(GroupType.USER)
) throw new SQLException("May only add Majordomo servers using Linux groups of type '"+GroupType.APPLICATION+"' or '"+GroupType.USER+"', trying to use '"+lsgType+'\'');
// Data integrity checks
int domain_linuxServer = getLinuxServerForDomain(conn, domain);
int userServer_linuxServer = LinuxAccountHandler.getServerForUserServer(conn, userServer);
if(domain_linuxServer!=userServer_linuxServer) throw new SQLException("((email.Domain.id="+domain+").ao_server='"+domain_linuxServer+"')!=((linux.UserServer.id="+userServer+").ao_server='"+userServer_linuxServer+"')");
int groupServer_linuxServer = LinuxAccountHandler.getServerForGroupServer(conn, groupServer);
if(domain_linuxServer!=groupServer_linuxServer) throw new SQLException("((email.Domain.id="+domain+").ao_server='"+domain_linuxServer+"')!=((linux.GroupServer.id="+groupServer+").ao_server='"+groupServer_linuxServer+"')");
// Disabled checks
Account.Name packageName=getPackageForDomain(conn, domain);
if(PackageHandler.isPackageDisabled(conn, packageName)) throw new SQLException("Unable to add Majordomo server: Package for domain #"+domain+" is disabled: "+packageName);
if(LinuxAccountHandler.isUserServerDisabled(conn, userServer)) throw new SQLException("Unable to add Majordomo server: UserServer disabled: "+userServer);
Account.Name lgPackageName=LinuxAccountHandler.getPackageForGroupServer(conn, groupServer);
if(PackageHandler.isPackageDisabled(conn, lgPackageName)) throw new SQLException("Unable to add Majordomo server: Package for GroupServer #"+groupServer+" is disabled: "+lgPackageName);
// Create the majordomo email pipe
DomainName domainName=getNetDomainForDomain(conn, domain);
PosixPath majordomoServerPath;
try {
majordomoServerPath = PosixPath.valueOf(MajordomoServer.MAJORDOMO_SERVER_DIRECTORY + "/" + domainName);
} catch(ValidationException e) {
throw new SQLException(e);
}
int majordomoPipe=addPipe0(conn, invalidateList, domain_linuxServer, majordomoServerPath+"/wrapper majordomo", packageName);
int majordomoAddress=getOrAddAddress(conn, invalidateList, MajordomoServer.MAJORDOMO_ADDRESS, domain);
int majordomoPipeAddress=addPipeAddress0(conn, invalidateList, majordomoAddress, majordomoPipe);
int ownerMajordomoAddress=getOrAddAddress(conn, invalidateList, MajordomoServer.OWNER_MAJORDOMO_ADDRESS, domain);
int majordomoOwnerAddress=getOrAddAddress(conn, invalidateList, MajordomoServer.MAJORDOMO_OWNER_ADDRESS, domain);
conn.executeUpdate(
"insert into\n"
+ " email.\"MajordomoServer\"\n"
+ "values(\n"
+ " ?,\n"
+ " ?,\n"
+ " ?,\n"
+ " ?,\n"
+ " ?,\n"
+ " ?,\n"
+ " ?\n"
+ ")",
domain,
userServer,
groupServer,
version,
majordomoPipeAddress,
ownerMajordomoAddress,
majordomoOwnerAddress
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.MAJORDOMO_SERVERS,
PackageHandler.getAccountForPackage(conn, packageName),
domain_linuxServer,
false
);
}
public static void disableList(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int disableLog,
int list
) throws IOException, SQLException {
AccountHandler.checkAccessDisableLog(conn, source, "disableList", disableLog, false);
checkAccessList(conn, source, "disableList", list);
if(isListDisabled(conn, list)) throw new SQLException("List is already disabled: "+list);
conn.executeUpdate(
"update email.\"List\" set disable_log=? where id=?",
disableLog,
list
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_LISTS,
getAccountForList(conn, list),
getLinuxServerForList(conn, list),
false
);
}
public static void disablePipe(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int disableLog,
int pipe
) throws IOException, SQLException {
AccountHandler.checkAccessDisableLog(conn, source, "disablePipe", disableLog, false);
checkAccessPipe(conn, source, "disablePipe", pipe);
if(isPipeDisabled(conn, pipe)) throw new SQLException("Pipe is already disabled: "+pipe);
conn.executeUpdate(
"update email.\"Pipe\" set disable_log=? where id=?",
disableLog,
pipe
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_PIPES,
getAccountForPipe(conn, pipe),
getLinuxServerForPipe(conn, pipe),
false
);
}
public static void disableSmtpRelay(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int disableLog,
int smtpRelay
) throws IOException, SQLException {
AccountHandler.checkAccessDisableLog(conn, source, "disableSmtpRelay", disableLog, false);
checkAccessSmtpRelay(conn, source, "disableSmtpRelay", smtpRelay);
if(isSmtpRelayDisabled(conn, smtpRelay)) throw new SQLException("SmtpRelay is already disabled: "+smtpRelay);
conn.executeUpdate(
"update email.\"SmtpRelay\" set disable_log=? where id=?",
disableLog,
smtpRelay
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_SMTP_RELAYS,
getAccountForSmtpRelay(conn, smtpRelay),
getLinuxServerForSmtpRelay(conn, smtpRelay),
false
);
}
public static void enableList(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int list
) throws IOException, SQLException {
checkAccessList(conn, source, "enableList", list);
int disableLog=getDisableLogForList(conn, list);
if(disableLog==-1) throw new SQLException("List is already enabled: "+list);
AccountHandler.checkAccessDisableLog(conn, source, "enableList", disableLog, true);
Account.Name pk=getPackageForList(conn, list);
if(PackageHandler.isPackageDisabled(conn, pk)) throw new SQLException("Unable to enable List #"+list+", Package not enabled: "+pk);
conn.executeUpdate(
"update email.\"List\" set disable_log=null where id=?",
list
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_LISTS,
PackageHandler.getAccountForPackage(conn, pk),
getLinuxServerForList(conn, list),
false
);
}
public static void enablePipe(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int pipe
) throws IOException, SQLException {
checkAccessPipe(conn, source, "enablePipe", pipe);
int disableLog=getDisableLogForPipe(conn, pipe);
if(disableLog==-1) throw new SQLException("Pipe is already enabled: "+pipe);
AccountHandler.checkAccessDisableLog(conn, source, "enablePipe", disableLog, true);
Account.Name pk=getPackageForPipe(conn, pipe);
if(PackageHandler.isPackageDisabled(conn, pk)) throw new SQLException("Unable to enable Pipe #"+pipe+", Package not enabled: "+pk);
conn.executeUpdate(
"update email.\"Pipe\" set disable_log=null where id=?",
pipe
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_PIPES,
PackageHandler.getAccountForPackage(conn, pk),
getLinuxServerForPipe(conn, pipe),
false
);
}
public static void enableSmtpRelay(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int smtpRelay
) throws IOException, SQLException {
checkAccessSmtpRelay(conn, source, "enableSmtpRelay", smtpRelay);
int disableLog=getDisableLogForSmtpRelay(conn, smtpRelay);
if(disableLog==-1) throw new SQLException("SmtpRelay is already enabled: "+smtpRelay);
AccountHandler.checkAccessDisableLog(conn, source, "enableSmtpRelay", disableLog, true);
Account.Name pk=getPackageForSmtpRelay(conn, smtpRelay);
if(PackageHandler.isPackageDisabled(conn, pk)) throw new SQLException("Unable to enable SmtpRelay #"+smtpRelay+", Package not enabled: "+pk);
conn.executeUpdate(
"update email.\"SmtpRelay\" set disable_log=null where id=?",
smtpRelay
);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.EMAIL_SMTP_RELAYS,
PackageHandler.getAccountForPackage(conn, pk),
getLinuxServerForSmtpRelay(conn, smtpRelay),
false
);
}
public static int getDisableLogForList(DatabaseConnection conn, int list) throws IOException, SQLException {
return conn.executeIntQuery("select coalesce(disable_log, -1) from email.\"List\" where id=?", list);
}
public static int getDisableLogForPipe(DatabaseConnection conn, int pipe) throws IOException, SQLException {
return conn.executeIntQuery("select coalesce(disable_log, -1) from email.\"Pipe\" where id=?", pipe);
}
public static int getDisableLogForSmtpRelay(DatabaseConnection conn, int smtpRelay) throws IOException, SQLException {
return conn.executeIntQuery("select coalesce(disable_log, -1) from email.\"SmtpRelay\" where id=?", smtpRelay);
}
public static String getListFile(
DatabaseConnection conn,
RequestSource source,
int list
) throws IOException, SQLException {
checkAccessList(conn, source, "getListFile", list);
PosixPath path = getPathForList(conn, list);
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(
conn,
getLinuxServerForList(conn, list)
);
conn.releaseConnection();
return daemonConnector.getEmailListFile(path);
}
public static IntList getListsForLinuxUserServer(
DatabaseConnection conn,
int linuxUserServer
) throws IOException, SQLException {
return conn.executeIntListQuery("select id from email.\"List\" where linux_server_account=?", linuxUserServer);
}
public static IntList getListsForPackage(
DatabaseConnection conn,
Account.Name packageName
) throws IOException, SQLException {
return conn.executeIntListQuery(
"select\n"
+ " el.id\n"
+ "from\n"
+ " linux.\"Group\" lg,\n"
+ " linux.\"GroupServer\" lsg,\n"
+ " email.\"List\" el\n"
+ "where\n"
+ " lg.package=?\n"
+ " and lg.name=lsg.name\n"
+ " and lsg.id=el.linux_server_group",
packageName
);
}
public static IntList getPipesForPackage(
DatabaseConnection conn,
Account.Name name
) throws IOException, SQLException {
return conn.executeIntListQuery("select id from email.\"Pipe\" where package=?", name);
}
public static long[] getImapFolderSizes(
DatabaseConnection conn,
RequestSource source,
int userServer,
String[] folderNames
) throws IOException, SQLException {
LinuxAccountHandler.checkAccessUserServer(conn, source, "getImapFolderSizes", userServer);
int linuxServer = LinuxAccountHandler.getServerForUserServer(conn, userServer);
if(DaemonHandler.isDaemonAvailable(linuxServer)) {
com.aoindustries.aoserv.client.linux.User.Name user = LinuxAccountHandler.getUserForUserServer(conn, userServer);
try {
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(conn, linuxServer);
conn.releaseConnection();
return daemonConnector.getImapFolderSizes(user, folderNames);
} catch(IOException err) {
logger.log(Level.SEVERE, "userServer="+userServer+", linuxServer="+linuxServer+", username="+user+", folderNames="+Arrays.asList(folderNames), err);
DaemonHandler.flagDaemonAsDown(linuxServer);
}
}
long[] sizes=new long[folderNames.length];
Arrays.fill(sizes, -1);
return sizes;
}
public static InboxAttributes getInboxAttributes(
DatabaseConnection conn,
RequestSource source,
int userServer
) throws IOException, SQLException {
LinuxAccountHandler.checkAccessUserServer(conn, source, "getInboxAttributes", userServer);
int linuxServer = LinuxAccountHandler.getServerForUserServer(conn, userServer);
if(DaemonHandler.isDaemonAvailable(linuxServer)) {
com.aoindustries.aoserv.client.linux.User.Name user = LinuxAccountHandler.getUserForUserServer(conn, userServer);
try {
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(conn, linuxServer);
conn.releaseConnection();
return daemonConnector.getInboxAttributes(user);
} catch(IOException err) {
logger.log(Level.SEVERE, "linux_server_account="+userServer+", linuxServer="+linuxServer+", username="+user, err);
DaemonHandler.flagDaemonAsDown(linuxServer);
}
}
return null;
}
public static IntList getSmtpRelaysForPackage(
DatabaseConnection conn,
Account.Name name
) throws IOException, SQLException {
return conn.executeIntListQuery("select id from email.\"SmtpRelay\" where package=?", name);
}
public static int getDomain(
DatabaseConnection conn,
int linuxServer,
String path
) throws IOException, SQLException {
return conn.executeIntQuery(
"select\n"
+ " el.id\n"
+ "from\n"
+ " email.\"List\" el,\n"
+ " linux.\"GroupServer\" lsg\n"
+ "where\n"
+ " el.path=path\n"
+ " and el.linux_server_group=lsg.id\n"
+ " and lsg.ao_server=?",
path,
linuxServer
);
}
public static int getDomainForAddress(
DatabaseConnection conn,
int address
) throws IOException, SQLException {
return conn.executeIntQuery("select domain from email.\"Address\" where id=?", address);
}
public static String getMajordomoInfoFile(
DatabaseConnection conn,
RequestSource source,
int majordomoList
) throws IOException, SQLException {
checkAccessList(conn, source, "getMajordomoInfoFile", majordomoList);
PosixPath infoPath;
try {
infoPath = PosixPath.valueOf(getPathForList(conn, majordomoList)+".info");
} catch(ValidationException e) {
throw new SQLException(e);
}
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(
conn,
getLinuxServerForList(conn, majordomoList)
);
conn.releaseConnection();
return daemonConnector.getEmailListFile(infoPath);
}
public static String getMajordomoIntroFile(
DatabaseConnection conn,
RequestSource source,
int majordomoList
) throws IOException, SQLException {
checkAccessList(conn, source, "getMajordomoIntroFile", majordomoList);
PosixPath introPath;
try {
introPath = PosixPath.valueOf(getPathForList(conn, majordomoList)+".intro");
} catch(ValidationException e) {
throw new SQLException(e);
}
AOServDaemonConnector daemonConnector = DaemonHandler.getDaemonConnector(
conn,
getLinuxServerForList(conn, majordomoList)
);
conn.releaseConnection();
return daemonConnector.getEmailListFile(introPath);
}
public static int getMajordomoServer(
DatabaseConnection conn,
int domain
) throws IOException, SQLException {
return conn.executeIntQuery(
"select\n"
+ " id\n"
+ "from\n"
+ " email.\"MajordomoServer\"\n"
+ "where\n"
+ " domain=?",
domain
);
}
public static void getSpamMessagesForSmtpRelay(
DatabaseConnection conn,
RequestSource source,
StreamableOutput out,
boolean provideProgress,
int esr
) throws IOException, SQLException {
com.aoindustries.aoserv.client.account.User.Name currentAdministrator = source.getCurrentAdministrator();
User masterUser=MasterServer.getUser(conn, currentAdministrator);
UserHost[] masterServers=masterUser==null?null:MasterServer.getUserHosts(conn, currentAdministrator);
if(masterUser!=null && masterServers.length==0) {
// TODO: release conn before writing to out
MasterServer.writeObjects(
conn,
source,
out,
provideProgress,
CursorMode.FETCH,
new SpamMessage(),
"select * from email.\"SpamMessage\" where email_relay=?",
esr
);
} else {
throw new SQLException("Only master users may access email.SpamMessage.");
}
}
public static void invalidateTable(Table.TableID tableID) {
if(tableID==Table.TableID.EMAIL_LISTS) {
synchronized(EmailHandler.class) {
disabledLists.clear();
}
} else if(tableID==Table.TableID.EMAIL_PIPES) {
synchronized(EmailHandler.class) {
disabledPipes.clear();
}
} else if(tableID==Table.TableID.EMAIL_SMTP_RELAYS) {
synchronized(EmailHandler.class) {
disabledSmtpRelays.clear();
}
}
}
public static boolean isListDisabled(DatabaseConnection conn, int list) throws IOException, SQLException {
synchronized(EmailHandler.class) {
Integer I = list;
Boolean O=disabledLists.get(I);
if(O!=null) return O;
boolean isDisabled=getDisableLogForList(conn, list)!=-1;
disabledLists.put(I, isDisabled);
return isDisabled;
}
}
public static boolean isPipeDisabled(DatabaseConnection conn, int pipe) throws IOException, SQLException {
synchronized(EmailHandler.class) {
Integer I = pipe;
Boolean O=disabledPipes.get(I);
if(O!=null) return O;
boolean isDisabled=getDisableLogForPipe(conn, pipe)!=-1;
disabledPipes.put(I, isDisabled);
return isDisabled;
}
}
public static boolean isSmtpRelayDisabled(DatabaseConnection conn, int smtpRelay) throws IOException, SQLException {
synchronized(EmailHandler.class) {
Integer I = smtpRelay;
Boolean O=disabledSmtpRelays.get(I);
if(O!=null) return O;
boolean isDisabled=getDisableLogForSmtpRelay(conn, smtpRelay)!=-1;
disabledSmtpRelays.put(I, isDisabled);
return isDisabled;
}
}
/**
* Refreshes a email SMTP relay.
*/
public static void refreshSmtpRelay(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int smtpRelay,
long minDuration
) throws IOException, SQLException {
checkAccessSmtpRelay(conn, source, "refreshSmtpRelay", smtpRelay);
if(isSmtpRelayDisabled(conn, smtpRelay)) throw new SQLException("Unable to refresh SmtpRelay, SmtpRelay disabled: "+smtpRelay);
Account.Name packageName=getPackageForSmtpRelay(conn, smtpRelay);
Account.Name account = PackageHandler.getAccountForPackage(conn, packageName);
int linuxServer = getLinuxServerForSmtpRelay(conn, smtpRelay);
Timestamp expiration=conn.executeTimestampQuery("select expiration from email.\"SmtpRelay\" where id=?", smtpRelay);
long exp=expiration==null?-1:expiration.getTime();
long min=minDuration==-1?-1:(System.currentTimeMillis()+minDuration); // TODO: Timestamp nanosecond precision
conn.executeUpdate(
"update email.\"SmtpRelay\" set last_refreshed=now(), refresh_count=refresh_count+1, expiration=? where id=?",
exp==-1 || min==-1
? null
: new Timestamp(Math.max(exp, min)),
smtpRelay
);
// Delete any old entries
conn.executeUpdate(
"delete from email.\"SmtpRelay\" where package=? and (ao_server is null or ao_server=?) and expiration is not null and now()::date-expiration::date>"+SmtpRelay.HISTORY_DAYS,
packageName,
linuxServer
);
// Notify all clients of the update
invalidateList.addTable(conn, Table.TableID.EMAIL_SMTP_RELAYS, account, linuxServer, false);
}
public static void removeBlackholeAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address
) throws IOException, SQLException {
checkAccessAddress(conn, source, "removeBlackholeAddress", address);
// Get stuff for use after the try block
Account.Name account = getAccountForAddress(conn, address);
int linuxServer = getLinuxServerForAddress(conn, address);
// Delete from the database
conn.executeUpdate("delete from email.\"BlackholeAddress\" where email_address=?", address);
// Notify all clients of the update
invalidateList.addTable(
conn,
Table.TableID.BLACKHOLE_EMAIL_ADDRESSES,
account,
linuxServer,
false
);
}
public static void removeAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int address
) throws IOException, SQLException {
checkAccessAddress(conn, source, "removeAddress", address);
// Get stuff for use after the try block
Account.Name account = getAccountForAddress(conn, address);
int linuxServer = getLinuxServerForAddress(conn, address);
// Delete the objects that depend on this one first
boolean isBlackhole=conn.executeBooleanQuery("select (select email_address from email.\"BlackholeAddress\" where email_address=?) is not null", address);
if(isBlackhole) conn.executeUpdate("delete from email.\"BlackholeAddress\" where email_address=?", address);
IntList ids=conn.executeIntListQuery("select id from email.\"InboxAddress\" where email_address=?", address);
boolean isLinuxAccAddress=ids.size()>0;
if(isLinuxAccAddress) {
for(int d=0;d 0;
boolean isEmailListAddress = conn.executeUpdate("delete from email.\"ListAddress\" where email_address=?", address) > 0;
boolean isEmailPipeAddress = conn.executeUpdate("delete from email.\"PipeAddress\" where email_address=?", address) > 0;
// Delete from the database
conn.executeUpdate("delete from email.\"Address\" where id=?", address);
// Notify all clients of the update
if(isBlackhole) invalidateList.addTable(conn, Table.TableID.BLACKHOLE_EMAIL_ADDRESSES, account, linuxServer, false);
if(isLinuxAccAddress) invalidateList.addTable(conn, Table.TableID.LINUX_ACC_ADDRESSES, account, linuxServer, false);
if(isEmailForwarding) invalidateList.addTable(conn, Table.TableID.EMAIL_FORWARDING, account, linuxServer, false);
if(isEmailListAddress) invalidateList.addTable(conn, Table.TableID.EMAIL_LIST_ADDRESSES, account, linuxServer, false);
if(isEmailPipeAddress) invalidateList.addTable(conn, Table.TableID.EMAIL_PIPE_ADDRESSES, account, linuxServer, false);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
public static void removeForwarding(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int forwarding
) throws IOException, SQLException {
int address = conn.executeIntQuery("select email_address from email.\"Forwarding\" where id=?", forwarding);
checkAccessAddress(conn, source, "removeForwarding", address);
// Get stuff for use after the try block
Account.Name account = getAccountForAddress(conn, address);
int linuxServer = getLinuxServerForAddress(conn, address);
// Delete from the database
conn.executeUpdate("delete from email.\"Forwarding\" where id=?", forwarding);
// Notify all clients of the update
invalidateList.addTable(conn, Table.TableID.EMAIL_FORWARDING, account, linuxServer, false);
}
public static void removeListAddress(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int listAddress
) throws IOException, SQLException {
int address = conn.executeIntQuery("select email_address from email.\"ListAddress\" where id=?", listAddress);
checkAccessAddress(conn, source, "removeListAddress", address);
// Get stuff for use after the try block
Account.Name account = getAccountForAddress(conn, address);
int linuxServer = getLinuxServerForAddress(conn, address);
// Delete from the database
conn.executeUpdate("delete from email.\"ListAddress\" where id=?", listAddress);
// Notify all clients of the update
invalidateList.addTable(conn, Table.TableID.EMAIL_LIST_ADDRESSES, account, linuxServer, false);
}
public static void removeList(
DatabaseConnection conn,
RequestSource source,
InvalidateList invalidateList,
int list
) throws IOException, SQLException {
checkAccessList(conn, source, "removeList", list);
removeList(conn, invalidateList, list);
}
public static void removeList(
DatabaseConnection conn,
InvalidateList invalidateList,
int list
) throws IOException, SQLException {
// Get the values for later use
Account.Name account = getAccountForList(conn, list);
int linuxServer = getLinuxServerForList(conn, list);
PosixPath path = conn.executeObjectQuery(ObjectFactories.posixPathFactory,
"select path from email.\"List\" where id=?",
list
);
// Delete the majordomo_list that is attached to this email list
if(isMajordomoList(conn, list)) {
// Get the listname_pipe_add and details
int listnameEPA=conn.executeIntQuery("select listname_pipe_add from email.\"MajordomoList\" where email_list=?", list);
int listnameEA=conn.executeIntQuery("select email_address from email.\"PipeAddress\" where id=?", listnameEPA);
int listnameEP=conn.executeIntQuery("select email_pipe from email.\"PipeAddress\" where id=?", listnameEPA);
// Get the listname_list_add and details
int listnameListELA=conn.executeIntQuery("select listname_list_add from email.\"MajordomoList\" where email_list=?", list);
int listnameListEA=conn.executeIntQuery("select email_address from email.\"ListAddress\" where id=?", listnameListELA);
// Get the listname_request_pipe_add and details
int listnameRequestEPA=conn.executeIntQuery("select listname_request_pipe_add from email.\"MajordomoList\" where email_list=?", list);
int listnameRequestEA=conn.executeIntQuery("select email_address from email.\"PipeAddress\" where id=?", listnameRequestEPA);
int listnameRequestEP=conn.executeIntQuery("select email_pipe from email.\"PipeAddress\" where id=?", listnameRequestEPA);
// Other direct email addresses
int ownerListnameEA=conn.executeIntQuery("select owner_listname_add from email.\"MajordomoList\" where email_list=?", list);
int listnameOwnerEA=conn.executeIntQuery("select listname_owner_add from email.\"MajordomoList\" where email_list=?", list);
int listnameApprovalEA=conn.executeIntQuery("select listname_approval_add from email.\"MajordomoList\" where email_list=?", list);
conn.executeUpdate("delete from email.\"MajordomoList\" where email_list=?", list);
invalidateList.addTable(conn, Table.TableID.MAJORDOMO_LISTS, account, linuxServer, false);
// Delete the listname_pipe_add
conn.executeUpdate("delete from email.\"PipeAddress\" where id=?", listnameEPA);
invalidateList.addTable(conn, Table.TableID.EMAIL_PIPE_ADDRESSES, account, linuxServer, false);
if(!isAddressUsed(conn, listnameEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", listnameEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
conn.executeUpdate("delete from email.\"Pipe\" where id=?", listnameEP);
invalidateList.addTable(conn, Table.TableID.EMAIL_PIPES, account, linuxServer, false);
// Delete the listname_list_add
conn.executeUpdate("delete from email.\"ListAddress\" where id=?", listnameListELA);
invalidateList.addTable(conn, Table.TableID.EMAIL_LIST_ADDRESSES, account, linuxServer, false);
if(!isAddressUsed(conn, listnameListEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", listnameListEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
// Delete the listname_pipe_add
conn.executeUpdate("delete from email.\"PipeAddress\" where id=?", listnameRequestEPA);
invalidateList.addTable(conn, Table.TableID.EMAIL_PIPE_ADDRESSES, account, linuxServer, false);
if(!isAddressUsed(conn, listnameRequestEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", listnameRequestEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
conn.executeUpdate("delete from email.\"Pipe\" where id=?", listnameRequestEP);
invalidateList.addTable(conn, Table.TableID.EMAIL_PIPES, account, linuxServer, false);
// Other direct email addresses
if(!isAddressUsed(conn, ownerListnameEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", ownerListnameEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
if(!isAddressUsed(conn, listnameOwnerEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", listnameOwnerEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
if(!isAddressUsed(conn, listnameApprovalEA)) {
conn.executeUpdate("delete from email.\"Address\" where id=?", listnameApprovalEA);
invalidateList.addTable(conn, Table.TableID.EMAIL_ADDRESSES, account, linuxServer, false);
}
}
// Delete the objects that depend on this one first
IntList addresses=conn.executeIntListQuery("select email_address from email.\"ListAddress\" where email_list=?", list);
int size=addresses.size();
boolean addressesModified=size>0;
for(int c=0;c0;
for(int c=0;c0;
for(int c=0;c0) {
for(int d=0;d0) {
for(int c=0;c
© 2015 - 2025 Weber Informatics LLC | Privacy Policy