I know I'am answering my own question, because I knew how to do it only after posting the question, so for anyone who may need this answer here it goes.
I used a wrap function that I made my self, like this:
def wrap(width, text):
lines = 
arr = text.split()
lengthSum = 0
strSum = ""
for var in arr:
lengthSum+=len(var) + 1
if lengthSum <= width:
strSum += " " + var
lengthSum = 0
strSum = var
lines.append(" " + arr[len(arr) - 1])
The width argument is the width of the panel in terms of number of characters that fit in there.
Then in the draw function I got the width of the panel like this:
tool_shelf = None
area = bpy.context.area
for region in area.regions:
if region.type == 'TOOLS':
tool_shelf = region
Where tool_shelf is now the panel I created, then I call the wrap function with the width and text like this:
lines = wrap(math.ceil(tool_shelf.width / 9), "Some long text that is out of borders")
I divided by 9 because
tool_shelf.width gives back the width in pixels, and I assumed 9 pixels for each character, now
lines is an array where every element is a line.
Then I write the lines in the panel like this:
for var in lines:
row = layout.row(align = True)
row.alignment = 'EXPAND'
I know this is not the optimal way, but anybody can get the main idea from this code and optimize it to their needs.
wrap is not in any class, but all the other codes are inside the
draw function of the class