10// Network returns tcp4 or tcp6, depending on the ip.
11// This network can be passed to Listen instead of "tcp", which may start listening
12// on both ipv4 and ipv6 for addresses 0.0.0.0 and ::, which can lead to errors
13// about the port already being in use.
14// For invalid IPs, "tcp" is returned.
15func Network(ip string) string {
26// DomainSPFIPs returns IPs to include in SPF records for domains. It includes the
27// IPs on listeners that have SMTP enabled, and includes IPs configured for SOCKS
29func DomainSPFIPs() (ips []net.IP) {
30 for _, l := range Conf.Static.Listeners {
31 if !l.SMTP.Enabled || l.IPsNATed {
35 if len(l.NATIPs) > 0 {
38 for _, ipstr := range ipstrs {
39 ip := net.ParseIP(ipstr)
40 if ip.IsUnspecified() {
46 for _, t := range Conf.Static.Transports {
48 ips = append(ips, t.Socks.IPs...)
54// IPs returns ip addresses we may be listening/receiving mail on or
55// connecting/sending from to the outside.
56func IPs(ctx context.Context, receiveOnly bool) ([]net.IP, error) {
57 log := pkglog.WithContext(ctx)
59 // Try to gather all IPs we are listening on by going through the config.
60 // If we encounter 0.0.0.0 or ::, we'll gather all local IPs afterwards.
62 var ipv4all, ipv6all bool
63 for _, l := range Conf.Static.Listeners {
64 // If NATed, we don't know our external IPs.
69 if len(l.NATIPs) > 0 {
72 for _, s := range check {
74 if ip.IsUnspecified() {
86 // We'll list the IPs on the interfaces. How useful is this? There is a good chance
87 // we're listening on all addresses because of a load balancer/firewall.
88 if ipv4all || ipv6all {
89 ifaces, err := net.Interfaces()
91 return nil, fmt.Errorf("listing network interfaces: %v", err)
93 for _, iface := range ifaces {
94 if iface.Flags&net.FlagUp == 0 {
97 addrs, err := iface.Addrs()
99 return nil, fmt.Errorf("listing addresses for network interface: %v", err)
105 for _, addr := range addrs {
106 ip, _, err := net.ParseCIDR(addr.String())
108 log.Errorx("bad interface addr", err, slog.Any("address", addr))
111 v4 := ip.To4() != nil
112 if ipv4all && v4 || ipv6all && !v4 {
113 ips = append(ips, ip)
123 for _, t := range Conf.Static.Transports {
125 ips = append(ips, t.Socks.IPs...)