summaryrefslogtreecommitdiff
path: root/tools/spf_example.c
blob: 30a84d6e28d143747d82d292e91e6717168bef28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 *  spf_example - An example program for how to use libspf2
 *
 */


/*
 * The libspf2 library uses the GNU autoconf system to help make
 * the library more portable.  The config.h file should have the
 * HAVE_xxx defines that are appropriate for your system.  Either use
 * autconf to create it, or create it by hand.
 */

#include "utils.h"

# include "spf_config.h"      /* jsd: copied from somewhere */
                /* not quite created by hand, */
                /* but not now automatic, either */

#ifdef STDC_HEADERS
# include <stdio.h>
# include <stdlib.h>       /* malloc / free */
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>  /* types (u_char .. etc..) */
#endif

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

#ifdef HAVE_STRING_H
# include <string.h>       /* strstr / strdup */
#else
# ifdef HAVE_STRINGS_H
#  include <strings.h>     /* strstr / strdup */
# endif
#endif

#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>   /* inet_ functions / structs */
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>   /* inet_ functions / structs */
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h> /* in_addr struct */
#endif

#ifdef HAVE_ARPA_NAMESER_H
# include <arpa/nameser.h> /* DNS HEADER struct */
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

/*
 * libspf2 public include files that are needed for this example
 * program
 */

#include <string>
#include <list>
#include <iostream>
#include <sstream>
#include "sepofra.h"

using namespace std;

/*
 * usage() just prints out the command line options for this program
 */
static void usage()
{
        fprintf(
        stderr,
        "Usage:\n"
        "   spf_example [options]\n"
        "\n"
        "Valid data options are:\n"
        "    -I <IP address>            The IP address that is sending email\n"
        "    -F <email address>         The email address used as the\n"
        "                               envelope MAIL FROM.  If no username (local\n"
        "                               part) is given, 'postmaster' will be\n"
        "                               assumed.\n"
        "    -T <email address>         [optional] The email address used as\n"
        "                               the envelope RCPT TO email address, for\n"
        "                               secondary-MX checking.\n"
        "    -H <domain name>           The domain name given on the SMTP HELO\n"
        "                               command.  This is only needed if the\n"
        "                               -F option is not given.\n"
        "    -d                         increase debug level.\n"
        "    -d5                        set debug level to 5.\n"
        );
}


/*
 * All the code is in the main routine, but most usages of libspf2
 * would have the code spread around into various subrotines.
 */

int main( int argc, char *argv[] )
{
  sepofra my_spf;
  int c;
  int     res = 0;

  string opt_ip;
  string opt_mailfrom;
  string opt_helo;
  string opt_rcpt_to;
  int   opt_debug = 0;

  /*
   * check the arguments
   */

  while (1)
  {
  c = getopt(argc, argv, "hI:F:H:T:d::" );

  if (c == -1)
          break;

  switch (c)
  {
  case 'h':
          usage();
          exit(0);
  case 'I':
          opt_ip = trim(optarg);
          break;

  case 'F':
          opt_mailfrom = trim(optarg, " \t\r\n<>");
          break;

  case 'H':
          opt_helo = trim(optarg, " \t\r\n<>");
          break;

  case 'T':
          opt_rcpt_to = optarg;
          break;

  case 0:
  case '?':
          goto helpout;
          break;

  case 'd':
          if (optarg == NULL)
          opt_debug++;
          else
          opt_debug = atoi( optarg );
          break;

  default:
          fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c);
  }
  }

  if (optind != argc) {
    fprintf(stderr, "extraneous verbiage: '%s'\n", argv[optind]);
    goto helpout;
  }
  if (!opt_ip.length()){
    fprintf(stderr, "Option -I 'IP.address' is required\n");
    goto helpout;
  }
  if (!opt_helo.length()){
    fprintf(stderr, "option '-H host.name' is required\n");
    goto helpout;
  }
  if (!opt_mailfrom.length()){
    fprintf(stderr, "option '-F mail@from' is required\n");
    goto helpout;
  }

  try {
    my_spf.check(opt_ip, opt_helo, opt_mailfrom, opt_rcpt_to, opt_debug);
    cout << "*** " << my_spf.explain() << endl;
  } catch (bad_thing foo) {
    cout << "Caught bad thing: " << foo.what() << endl;
  }
  return 0;

helpout:
  fprintf(stderr, "for help try -h\n");
  res = 255;
  return res;

}