Revision 296e14301a7aa23a5ee2bfaa1210af54e594cbbf authored by Guido van Rossum on 07 April 1999, 15:03:39 UTC, committed by Guido van Rossum on 07 April 1999, 15:03:39 UTC
Per writes: """ The application where Signum Support uses smtplib needs to be able to report good error messages to the user when sending email fails. To help in diagnosing problems it is useful to be able to report the entire message sent by the server, not only the SMTP error code of the offending command. A lot of the functions in sendmail.py unfortunately discards the message, leaving only the code. The enclosed patch fixes that problem. The enclosed patch also introduces a base class for exceptions that include an SMTP error code and error message, and make the code and message available on separate attributes, so that surrounding code can deal with them in whatever way it sees fit. I've also added some documentation to the exception classes. The constructor will now raise an exception if it cannot connect to the SMTP server. The data() method will raise an SMTPDataError if it doesn't receive the expected 354 code in the middle of the exchange. According to section 5.2.10 of RFC 1123 a smtp client must accept "any text, including no text at all" after the error code. If the response of a HELO command contains no text self.helo_resp will be set to the empty string (""). The patch fixes the test in the sendmail() method so that helo_resp is tested against None; if it has the empty string as value the sendmail() method would invoke the helo() method again. The code no longer accepts a -1 reply from the ehlo() method in sendmail(). [Text about removing SMTPRecipientsRefused deleted --GvR] """ and also: """ smtplib.py appends an extra blank line to the outgoing mail if the `msg' argument to the sendmail method already contains a trailing newline. This patch should fix the problem. """ The Dragon writes: """ Mostly I just re-added the SMTPRecipientsRefused exception (the exeption object now has the appropriate info in it ) [Per had removed this in his patch --GvR] and tweaked the behavior of the sendmail method whence it throws the newly added SMTPHeloException (it was closing the connection, which it shouldn't. whatever catches the exception should do that. ) I pondered the change of the return values to tuples all around, and after some thinking I decided that regularizing the return values was too much of the Right Thing (tm) to not do. My one concern is that code expecting an integer & getting a tuple may fail silently. (i.e. if it's doing : x.somemethod() >= 400: expecting an integer, the expression will always be true if it gets a tuple instead. ) However, most smtplib code I've seen only really uses the sendmail() method, so this wouldn't bother it. Usually code I've seen that calls the other methods usually only calls helo() and ehlo() for doing ESMTP, a feature which was not in the smtplib included with 1.5.1, and thus I would think not much code uses it yet. """
1 parent 630a9a6
sliceobject.c
/*
Written by Jim Hugunin and Chris Chase.
This includes both the singular ellipsis object and slice objects.
Guido, feel free to do whatever you want in the way of copyrights
for this file.
*/
/*
Py_Ellipsis encodes the '...' rubber index token. It is similar to
the Py_NoneStruct in that there is no way to create other objects of
this type and there is exactly one in existence.
*/
#include "Python.h"
static PyObject *
ellipsis_repr(op)
PyObject *op;
{
return PyString_FromString("Ellipsis");
}
static PyTypeObject PyEllipsis_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
"ellipsis",
0,
0,
0, /*tp_dealloc*/ /*never called*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)ellipsis_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
};
PyObject _Py_EllipsisObject = {
PyObject_HEAD_INIT(&PyEllipsis_Type)
};
/* Slice object implementation
start, stop, and step are python objects with None indicating no
index is present.
*/
PyObject *
PySlice_New(start, stop, step)
PyObject *start;
PyObject *stop;
PyObject *step;
{
PySliceObject *obj =
(PySliceObject *) PyObject_NEW(PySliceObject, &PySlice_Type);
if (step == NULL) step = Py_None;
Py_INCREF(step);
if (start == NULL) start = Py_None;
Py_INCREF(start);
if (stop == NULL) stop = Py_None;
Py_INCREF(stop);
obj->step = step;
obj->start = start;
obj->stop = stop;
return (PyObject *) obj;
}
int
PySlice_GetIndices(r, length, start, stop, step)
PySliceObject *r;
int length;
int *start;
int *stop;
int *step;
{
if (r->step == Py_None) {
*step = 1;
} else {
if (!PyInt_Check(r->step)) return -1;
*step = PyInt_AsLong(r->step);
}
if (r->start == Py_None) {
*start = *step < 0 ? length-1 : 0;
} else {
if (!PyInt_Check(r->start)) return -1;
*start = PyInt_AsLong(r->start);
if (*start < 0) *start += length;
}
if (r->stop == Py_None) {
*stop = *step < 0 ? -1 : length;
} else {
if (!PyInt_Check(r->stop)) return -1;
*stop = PyInt_AsLong(r->stop);
if (*stop < 0) *stop += length;
}
if (*stop > length) return -1;
if (*start >= length) return -1;
if (*step == 0) return -1;
return 0;
}
static void
slice_dealloc(r)
PySliceObject *r;
{
Py_DECREF(r->step);
Py_DECREF(r->start);
Py_DECREF(r->stop);
PyMem_DEL(r);
}
static PyObject *
slice_repr(r)
PySliceObject *r;
{
PyObject *s, *comma;
s = PyString_FromString("slice(");
comma = PyString_FromString(", ");
PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
PyString_Concat(&s, comma);
PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
PyString_Concat(&s, comma);
PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
PyString_ConcatAndDel(&s, PyString_FromString(")"));
Py_DECREF(comma);
return s;
}
static PyObject *slice_getattr(self, name)
PySliceObject *self;
char *name;
{
PyObject *ret;
ret = NULL;
if (strcmp(name, "start") == 0) {
ret = self->start;
}
else if (strcmp(name, "stop") == 0) {
ret = self->stop;
}
else if (strcmp(name, "step") == 0) {
ret = self->step;
}
else if (strcmp(name, "__members__") == 0) {
return Py_BuildValue("[sss]",
"start", "stop", "step");
}
else {
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
Py_INCREF(ret);
return ret;
}
PyTypeObject PySlice_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* Number of items for varobject */
"slice", /* Name of this type */
sizeof(PySliceObject), /* Basic object size */
0, /* Item size for varobject */
(destructor)slice_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)slice_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)slice_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...