
org.subethamail.smtp.internal.io.ReceivedHeaderStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of subethasmtp Show documentation
Show all versions of subethasmtp Show documentation
A fork of a fork (!) of SubEtha, an easy-to-use server-side SMTP library for Java.
/*
*
*/
package org.subethamail.smtp.internal.io;
import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Optional;
import org.subethamail.smtp.internal.util.TextUtils;
import com.github.davidmoten.guavamini.Preconditions;
/**
* Prepends a Received: header at the beginning of the input stream.
*/
public final class ReceivedHeaderStream extends FilterInputStream {
ByteArrayInputStream header;
/**
* Constructor.
*
* @param softwareName
* A software name and version, or null if this information
* should not be printed
* @param singleRecipient
* The single recipient of the message. If there are more than
* one recipients then this must be null.
*/
/**
* @param in
* @param heloHost
* @param host
* @param whoami
* @param softwareName
* @param id
* @param singleRecipient
*/
public ReceivedHeaderStream(InputStream in, Optional heloHost, InetAddress host,
String whoami, Optional softwareName, String id,
Optional singleRecipient) {
super(in);
/*
* Looks like: Received: from iamhelo (wasabi.infohazard.org
* [209.237.247.14]) by mx.google.com with SMTP id
* 32si2669129wfa.13.2009.05.27.18.27.31; Wed, 27 May 2009 18:27:48
* -0700 (PDT)
*/
Preconditions.checkNotNull(heloHost);
Preconditions.checkNotNull(softwareName);
Preconditions.checkNotNull(singleRecipient);
DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z (z)", Locale.US);
String timestamp = fmt.format(new Date());
StringBuilder header = new StringBuilder();
header.append("Received: from " + heloHost.orElse(null) + " (" + constructTcpInfo(host)
+ ")\r\n");
header.append(" by " + whoami + "\r\n");
header.append(" with SMTP");
if (softwareName.isPresent())
header.append(" (" + softwareName.get() + ")");
header.append(" id ").append(id);
if (singleRecipient.isPresent())
header.append("\r\n for " + singleRecipient.get());
header.append(";\r\n");
header.append(" " + timestamp + "\r\n");
this.header = new ByteArrayInputStream(TextUtils.getAsciiBytes(header.toString()));
}
/**
* Returns a formatted TCP-info element, depending on the success of the IP
* address name resolution either with domain name or only the address
* literal.
*
* @param host
* the address of the remote SMTP client.
* @return the formatted TCP-info element as defined by RFC 5321
*/
private String constructTcpInfo(InetAddress host) {
// if it is not successful it just returns the address
String domain = host.getCanonicalHostName();
String address = host.getHostAddress();
// check whether the host name resolution was successful
if (domain.equals(address))
return "[" + address + "]";
else
return domain + " [" + address + "]";
}
/* */
@Override
public int available() throws IOException {
return this.header.available() + super.available();
}
/* */
@Override
public void close() throws IOException {
super.close();
}
/* */
@Override
public synchronized void mark(int readlimit) {
throw new UnsupportedOperationException();
}
/* */
@Override
public boolean markSupported() {
return false;
}
/* */
@Override
public int read() throws IOException {
if (this.header.available() > 0)
return this.header.read();
else
return super.read();
}
/* */
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (this.header.available() > 0) {
int countRead = this.header.read(b, off, len);
if (countRead < len) {
// We need to add a little extra from the normal stream
int remainder = len - countRead;
int additionalRead = super.read(b, off + countRead, remainder);
return countRead + additionalRead;
} else
return countRead;
} else
return super.read(b, off, len);
}
/* */
@Override
public int read(byte[] b) throws IOException {
return this.read(b, 0, b.length);
}
/* */
@Override
public synchronized void reset() throws IOException {
throw new UnsupportedOperationException();
}
/* */
@Override
public long skip(long n) throws IOException {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy